Normalize line endings

This commit is contained in:
KrazyTheFox
2017-12-28 23:40:29 -05:00
parent 251569e81c
commit 6d5e56f6bf
6957 changed files with 391658 additions and 414049 deletions

0
forge-gui/src/main/config/create-dmg Executable file → Normal file
View File

0
forge-gui/src/main/config/forge.command Executable file → Normal file
View File

0
forge-gui/src/main/config/forge.sh Executable file → Normal file
View File

0
forge-gui/src/main/config/support/dmg-license.py Executable file → Normal file
View File

View File

@@ -1,100 +1,100 @@
<html>
<head>
<title>Tail-based by Web Sockets</title>
<link href="css/core.css" media="all" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/observable.js"></script>
<script type="text/javascript" src="js/socket.js"></script>
<script type='text/javascript' src="js/main.js"></script>
</head>
<body>
<div class="wrap">
<div class="title">
<span>Your server: <b>ws://</b></span>
<input id="ws_uri" type="text" value="localhost:81/" name="uri"/>
<button id="connect" name="connect" class="cn">Connect</button>
<button id="disconn" name="disconn" class="dc" disabled="disabled">Disconnect</button>
</div>
<ul class="messages" id='messages'></ul>
<div class="packets" id='input'>
<span>Raw text to send:</span>
<input type="text" name="packet" value="" />
<button id="send" class="send">Send</button>
</div>
</div>
<script type="text/javascript">
if (!window.WebSocket)
alert("WebSocket not supported by this browser");
var server = Socket();
var listener = {
onOpen : function() {
$('#input').slideDown();
},
onMessage : function(m) {
if (m.data) {
addLi("incoming", m.data);
}
},
onClose : function(m) {
addLi("error", "Connection was closed (" + m.code + "): " + m.reason);
onDisconnectClicked();
$('#input').fadeOut();
}
};
server.addObserver(listener);
function addLi(className, text) {
var spanText = document.createElement('li');
spanText.className = className;
spanText.innerHTML = text;
var messageBox = $('#messages')[0];
messageBox.appendChild(spanText);
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
}
function onConnectClicked() {
var uri = $("#ws_uri").val()
addLi("connecting", "Connecting to ws://" + uri + " ..." )
server.connect(uri);
$('#connect').attr("disabled", "disabled")
$('#disconn').removeAttr("disabled")
}
function onDisconnectClicked() {
server.close();
$('#disconn').attr("disabled", "disabled")
$('#connect').removeAttr("disabled")
}
function onSendClicked() {
var toSend = $("#input input").val();
$("#input input").val("");
addLi("outcoming", toSend);
server.send(toSend)
}
function onInputKey(event) {
if( event.keyCode == 13 )
onSendClicked();
}
function onReady() {
$('#connect').on("click", onConnectClicked);
$('#disconn').on("click", onDisconnectClicked);
$('#send').on("click", onSendClicked);
$("#input input").on("keypress", onInputKey);
}
$(onReady)
</script>
</body>
<html>
<head>
<title>Tail-based by Web Sockets</title>
<link href="css/core.css" media="all" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/observable.js"></script>
<script type="text/javascript" src="js/socket.js"></script>
<script type='text/javascript' src="js/main.js"></script>
</head>
<body>
<div class="wrap">
<div class="title">
<span>Your server: <b>ws://</b></span>
<input id="ws_uri" type="text" value="localhost:81/" name="uri"/>
<button id="connect" name="connect" class="cn">Connect</button>
<button id="disconn" name="disconn" class="dc" disabled="disabled">Disconnect</button>
</div>
<ul class="messages" id='messages'></ul>
<div class="packets" id='input'>
<span>Raw text to send:</span>
<input type="text" name="packet" value="" />
<button id="send" class="send">Send</button>
</div>
</div>
<script type="text/javascript">
if (!window.WebSocket)
alert("WebSocket not supported by this browser");
var server = Socket();
var listener = {
onOpen : function() {
$('#input').slideDown();
},
onMessage : function(m) {
if (m.data) {
addLi("incoming", m.data);
}
},
onClose : function(m) {
addLi("error", "Connection was closed (" + m.code + "): " + m.reason);
onDisconnectClicked();
$('#input').fadeOut();
}
};
server.addObserver(listener);
function addLi(className, text) {
var spanText = document.createElement('li');
spanText.className = className;
spanText.innerHTML = text;
var messageBox = $('#messages')[0];
messageBox.appendChild(spanText);
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
}
function onConnectClicked() {
var uri = $("#ws_uri").val()
addLi("connecting", "Connecting to ws://" + uri + " ..." )
server.connect(uri);
$('#connect').attr("disabled", "disabled")
$('#disconn').removeAttr("disabled")
}
function onDisconnectClicked() {
server.close();
$('#disconn').attr("disabled", "disabled")
$('#connect').removeAttr("disabled")
}
function onSendClicked() {
var toSend = $("#input input").val();
$("#input input").val("");
addLi("outcoming", toSend);
server.send(toSend)
}
function onInputKey(event) {
if( event.keyCode == 13 )
onSendClicked();
}
function onReady() {
$('#connect').on("click", onConnectClicked);
$('#disconn').on("click", onDisconnectClicked);
$('#send').on("click", onSendClicked);
$("#input input").on("keypress", onInputKey);
}
$(onReady)
</script>
</body>
</html>

View File

@@ -1,23 +1,23 @@
ul, ol { margin: 0; }
div { border: 0px solid black; }
div.wrap { width: 640px; margin: 100px auto;}
.title { height: 24px; background-color: #ddd; padding: 4px; border: 1px solid black; border-bottom: 0px }
.title input {width: 300px; }
.title span { display: inline-block; width: 120px; text-align: right; }
.messages { height: 30ex; overflow: auto; background-color: #fff; padding: 4px; border: 1px solid black; list-style: none; }
.messages .incoming { color: #006; }
.messages .incoming:before { content: "<< "}
.messages .outcoming { color: #060; }
.messages .outcoming:before { content: ">> "}
.messages .error { color: #600; }
.messages li:nth-child(2n) { background-color: #f7f7f7; }
.packets { padding: 4px; background-color: #ddd; border: 1px solid black; border-top: 0px; display: none; }
.packets span { display: inline-block; width: 120px; text-align: right; }
.packets input {width: 400px; }
.packets button { width: 100px; }
ul, ol { margin: 0; }
div { border: 0px solid black; }
div.wrap { width: 640px; margin: 100px auto;}
.title { height: 24px; background-color: #ddd; padding: 4px; border: 1px solid black; border-bottom: 0px }
.title input {width: 300px; }
.title span { display: inline-block; width: 120px; text-align: right; }
.messages { height: 30ex; overflow: auto; background-color: #fff; padding: 4px; border: 1px solid black; list-style: none; }
.messages .incoming { color: #006; }
.messages .incoming:before { content: "<< "}
.messages .outcoming { color: #060; }
.messages .outcoming:before { content: ">> "}
.messages .error { color: #600; }
.messages li:nth-child(2n) { background-color: #f7f7f7; }
.packets { padding: 4px; background-color: #ddd; border: 1px solid black; border-top: 0px; display: none; }
.packets span { display: inline-block; width: 120px; text-align: right; }
.packets input {width: 400px; }
.packets button { width: 100px; }
span.alert { font-style: italic; }

View File

@@ -1,23 +1,23 @@
var Observable = function(eventNames) {
var _t = {};
var observers = {};
_t.addObserver = function(obj) {
for(var i = 0; i < eventNames.length; i++) {
var evName = eventNames[i]
var method = obj["on" + evName];
if( typeof(method) === 'function') {
var handlers = observers[evName]
if( 'undefined' === typeof(handler))
handlers = observers[evName] = [];
handlers.push(obj);
}
}
}
_t.fireEvent = function() { // usually invoked as .apply(EventName, args)
var q = observers[this]
if ( q ) for( var i = 0; i < q.length; i++ ) q[i]['on'+ this].apply(q[i], arguments);
}
return _t;
var Observable = function(eventNames) {
var _t = {};
var observers = {};
_t.addObserver = function(obj) {
for(var i = 0; i < eventNames.length; i++) {
var evName = eventNames[i]
var method = obj["on" + evName];
if( typeof(method) === 'function') {
var handlers = observers[evName]
if( 'undefined' === typeof(handler))
handlers = observers[evName] = [];
handlers.push(obj);
}
}
}
_t.fireEvent = function() { // usually invoked as .apply(EventName, args)
var q = observers[this]
if ( q ) for( var i = 0; i < q.length; i++ ) q[i]['on'+ this].apply(q[i], arguments);
}
return _t;
}

View File

@@ -1,27 +1,27 @@
// There should be some kind of fallback to Flash-powered sockets (IE 9-, Opera with sockets switched off)
var Socket = function() {
var _t = Observable(["Open", "Message", "Close", "Error"]);
function onOpen() { _t.fireEvent.apply("Open", arguments); }
function onClose() { _t.fireEvent.apply("Close", arguments); }
function onError() { _t.fireEvent.apply("Error", arguments); }
function onMessage() { _t.fireEvent.apply("Message", arguments); }
var ws;
_t.connect = function(location) {
ws = new WebSocket("ws://" + location);
ws.onopen = onOpen;
ws.onmessage = onMessage;
ws.onclose = onClose;
ws.onerror = onError;
}
// _t.getWs = function() { return ws; }
_t.isOpen = function() { return ws && ws.readyState == ws.OPEN; }
_t.close = function() { ws && ws.close(); }
_t.send = function(text) { text != null && text.length > 0 && ws && ws.send(text); };
return _t;
};
// There should be some kind of fallback to Flash-powered sockets (IE 9-, Opera with sockets switched off)
var Socket = function() {
var _t = Observable(["Open", "Message", "Close", "Error"]);
function onOpen() { _t.fireEvent.apply("Open", arguments); }
function onClose() { _t.fireEvent.apply("Close", arguments); }
function onError() { _t.fireEvent.apply("Error", arguments); }
function onMessage() { _t.fireEvent.apply("Message", arguments); }
var ws;
_t.connect = function(location) {
ws = new WebSocket("ws://" + location);
ws.onopen = onOpen;
ws.onmessage = onMessage;
ws.onclose = onClose;
ws.onerror = onError;
}
// _t.getWs = function() { return ws; }
_t.isOpen = function() { return ws && ws.readyState == ws.OPEN; }
_t.close = function() { ws && ws.close(); }
_t.send = function(text) { text != null && text.length > 0 && ws && ws.send(text); };
return _t;
};

View File

@@ -1,95 +1,95 @@
package forge;
import forge.util.ThreadUtil;
public class FThreads {
private FThreads() { } // no instances supposed
/** Checks if calling method uses event dispatch thread.
* Exception thrown if method is on "wrong" thread.
* A boolean is passed to indicate if the method must be EDT or not.
*
* @param methodName &emsp; String, part of the custom exception message.
* @param mustBeEDT &emsp; boolean: true = exception if not EDT, false = exception if EDT
*/
public static void assertExecutedByEdt(final boolean mustBeEDT) {
if (isGuiThread() != mustBeEDT) {
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
final String modalOperator = mustBeEDT ? " must be" : " may not be";
throw new IllegalStateException(methodName + modalOperator + " accessed from the event dispatch thread.");
}
}
public static void invokeInEdtLater(final Runnable proc) {
GuiBase.getInterface().invokeInEdtLater(proc);
}
public static void invokeInEdtNowOrLater(final Runnable proc) {
if (isGuiThread()) {
GuiBase.getInterface().invokeInEdtNow(proc);
}
else {
GuiBase.getInterface().invokeInEdtLater(proc);
}
}
/**
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
* feasible.</B>
*
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
* rethrown as RuntimeExceptions.
*
* @param proc
* the Runnable to run
* @see fgd.SwingUtilities#invokeLater(Runnable)
*/
public static void invokeInEdtAndWait(final Runnable proc) {
GuiBase.getInterface().invokeInEdtAndWait(proc);
}
private static int backgroundThreadCount;
public static void invokeInBackgroundThread(final Runnable proc) {
//start thread name with "Game" so isGuiThread() returns false on GuiMobile
new Thread(proc, "Game BT" + backgroundThreadCount).start();
backgroundThreadCount++;
}
public static boolean isGuiThread() {
return GuiBase.getInterface().isGuiThread();
}
public static void delayInEDT(final int milliseconds, final Runnable inputUpdater) {
final Runnable runInEdt = new Runnable() {
@Override
public void run() {
FThreads.invokeInEdtNowOrLater(inputUpdater);
}
};
ThreadUtil.delay(milliseconds, runInEdt);
}
public static String debugGetCurrThreadId() {
return isGuiThread() ? "EDT" : Thread.currentThread().getName();
}
public static String debugGetStackTraceItem(final int depth, final boolean shorter) {
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String lastItem = trace[depth].toString();
if (shorter) {
int lastPeriod = lastItem.lastIndexOf('.');
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastItem = lastItem.substring(lastPeriod+1);
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
}
return String.format("%s > %s called from %s", debugGetCurrThreadId(),
trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem);
}
public static String debugGetStackTraceItem(final int depth) {
return debugGetStackTraceItem(depth, false);
}
}
package forge;
import forge.util.ThreadUtil;
public class FThreads {
private FThreads() { } // no instances supposed
/** Checks if calling method uses event dispatch thread.
* Exception thrown if method is on "wrong" thread.
* A boolean is passed to indicate if the method must be EDT or not.
*
* @param methodName &emsp; String, part of the custom exception message.
* @param mustBeEDT &emsp; boolean: true = exception if not EDT, false = exception if EDT
*/
public static void assertExecutedByEdt(final boolean mustBeEDT) {
if (isGuiThread() != mustBeEDT) {
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
final String modalOperator = mustBeEDT ? " must be" : " may not be";
throw new IllegalStateException(methodName + modalOperator + " accessed from the event dispatch thread.");
}
}
public static void invokeInEdtLater(final Runnable proc) {
GuiBase.getInterface().invokeInEdtLater(proc);
}
public static void invokeInEdtNowOrLater(final Runnable proc) {
if (isGuiThread()) {
GuiBase.getInterface().invokeInEdtNow(proc);
}
else {
GuiBase.getInterface().invokeInEdtLater(proc);
}
}
/**
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
* feasible.</B>
*
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
* rethrown as RuntimeExceptions.
*
* @param proc
* the Runnable to run
* @see fgd.SwingUtilities#invokeLater(Runnable)
*/
public static void invokeInEdtAndWait(final Runnable proc) {
GuiBase.getInterface().invokeInEdtAndWait(proc);
}
private static int backgroundThreadCount;
public static void invokeInBackgroundThread(final Runnable proc) {
//start thread name with "Game" so isGuiThread() returns false on GuiMobile
new Thread(proc, "Game BT" + backgroundThreadCount).start();
backgroundThreadCount++;
}
public static boolean isGuiThread() {
return GuiBase.getInterface().isGuiThread();
}
public static void delayInEDT(final int milliseconds, final Runnable inputUpdater) {
final Runnable runInEdt = new Runnable() {
@Override
public void run() {
FThreads.invokeInEdtNowOrLater(inputUpdater);
}
};
ThreadUtil.delay(milliseconds, runInEdt);
}
public static String debugGetCurrThreadId() {
return isGuiThread() ? "EDT" : Thread.currentThread().getName();
}
public static String debugGetStackTraceItem(final int depth, final boolean shorter) {
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String lastItem = trace[depth].toString();
if (shorter) {
int lastPeriod = lastItem.lastIndexOf('.');
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastItem = lastItem.substring(lastPeriod+1);
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
}
return String.format("%s > %s called from %s", debugGetCurrThreadId(),
trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem);
}
public static String debugGetStackTraceItem(final int depth) {
return debugGetStackTraceItem(depth, false);
}
}

View File

@@ -1,14 +1,14 @@
package forge;
import forge.interfaces.IGuiBase;
public class GuiBase {
private static IGuiBase guiInterface;
public static IGuiBase getInterface() {
return guiInterface;
}
public static void setInterface(IGuiBase i0) {
guiInterface = i0;
}
}
package forge;
import forge.interfaces.IGuiBase;
public class GuiBase {
private static IGuiBase guiInterface;
public static IGuiBase getInterface() {
return guiInterface;
}
public static void setInterface(IGuiBase i0) {
guiInterface = i0;
}
}

View File

@@ -1,270 +1,270 @@
package forge.achievement;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.w3c.dom.Element;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.properties.ForgeConstants;
import forge.util.Lang;
import forge.util.XmlUtil;
public abstract class Achievement {
private final String key, displayName, sharedDesc, commonDesc, uncommonDesc, rareDesc, mythicDesc;
private final int commonThreshold, uncommonThreshold, rareThreshold, mythicThreshold;
private final boolean checkGreaterThan;
protected final int defaultValue;
private ISkinImage image;
private long timestamp;
private int best;
//use this constructor for special achievements without tiers
protected Achievement(final String key0, final String displayName0, final String description0, final String flavorText0, final int defaultValue0) {
this(key0, displayName0, description0, defaultValue0, null, 1, null, 1, null, 1, "(" + flavorText0 + ")", 1); //pass flavor text as mythic description so it appears below description faded out
}
//use this constructor for regular tiered achievements
protected Achievement(final String key0, final String displayName0, final String sharedDesc0, final int defaultValue0,
final String commonDesc0, final int commonThreshold0,
final String uncommonDesc0, final int uncommonThreshold0,
final String rareDesc0, final int rareThreshold0,
final String mythicDesc0, final int mythicThreshold0) {
key = key0;
displayName = displayName0;
sharedDesc = sharedDesc0;
commonDesc = commonDesc0;
commonThreshold = commonThreshold0;
uncommonDesc = uncommonDesc0;
uncommonThreshold = uncommonThreshold0;
rareDesc = rareDesc0;
rareThreshold = rareThreshold0;
mythicDesc = mythicDesc0;
mythicThreshold = mythicThreshold0;
checkGreaterThan = rareThreshold0 >= uncommonThreshold0;
best = defaultValue0;
defaultValue = defaultValue0;
}
public String getKey() {
return key;
}
public String getDisplayName() {
return displayName;
}
public String getSharedDesc() {
return sharedDesc;
}
public String getCommonDesc() {
return commonDesc;
}
public String getUncommonDesc() {
return uncommonDesc;
}
public String getRareDesc() {
return rareDesc;
}
public String getMythicDesc() {
return mythicDesc;
}
public ISkinImage getImage() {
if (image == null) {
updateTrophyImage();
}
return image;
}
public int getBest() {
return best;
}
public boolean isSpecial() {
return mythicThreshold == commonThreshold;
}
private boolean earnedSpecial() {
return (isSpecial() && best > 0);
}
public boolean earnedMythic() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= mythicThreshold;
}
return best <= mythicThreshold;
}
public boolean earnedRare() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= rareThreshold;
}
return best <= rareThreshold;
}
public boolean earnedUncommon() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= uncommonThreshold;
}
return best <= uncommonThreshold;
}
public boolean earnedCommon() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= commonThreshold;
}
return best <= commonThreshold;
}
//get card associated with this achievement if any
public IPaperCard getPaperCard() {
return null;
}
protected abstract int evaluate(Player player, Game game);
private void updateTrophyImage() {
FSkinProp background;
float opacity = 1;
if (earnedSpecial()) {
background = FSkinProp.IMG_SPECIAL_TROPHY;
}
else if (earnedMythic()) {
background = FSkinProp.IMG_MYTHIC_TROPHY;
}
else if (earnedRare()) {
background = FSkinProp.IMG_RARE_TROPHY;
}
else if (earnedUncommon()) {
background = FSkinProp.IMG_UNCOMMON_TROPHY;
}
else if (earnedCommon()) {
background = FSkinProp.IMG_COMMON_TROPHY;
}
else {
opacity = 0.25f; //fade out if achievement hasn't been earned yet
if (mythicThreshold == commonThreshold) {
background = FSkinProp.IMG_SPECIAL_TROPHY;
}
else {
background = FSkinProp.IMG_COMMON_TROPHY;
}
}
image = GuiBase.getInterface().createLayeredImage(background, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + key + ".png", opacity);
}
public int update(final Player player) {
final int value = evaluate(player, player.getGame());
if (checkGreaterThan) {
if (value <= best) { return value; }
}
else if (value >= best) { return value; }
final boolean hadEarnedSpecial = earnedSpecial();
final boolean hadEarnedMythic = earnedMythic();
final boolean hadEarnedRare = earnedRare();
final boolean hadEarnedUncommon = earnedUncommon();
final boolean hadEarnedCommon = earnedCommon();
best = value;
timestamp = new Date().getTime();
if (earnedSpecial()) {
if (!hadEarnedSpecial) {
updateTrophyImage();
GuiBase.getInterface().showImageDialog(image, displayName + "\n" + sharedDesc + "\n" + mythicDesc, "Achievement Earned");
}
return value;
}
String type = null;
String desc = null;
if (earnedMythic()) {
if (!hadEarnedMythic) {
type = "Mythic";
desc = mythicDesc;
}
}
else if (earnedRare()) {
if (!hadEarnedRare) {
type = "Rare";
desc = rareDesc;
}
}
else if (earnedUncommon()) {
if (!hadEarnedUncommon) {
type = "Uncommon";
desc = uncommonDesc;
}
}
else if (earnedCommon()) {
if (!hadEarnedCommon) {
type = "Common";
desc = commonDesc;
}
}
if (type != null) {
updateTrophyImage();
if (sharedDesc != null) {
desc = sharedDesc + " " + desc;
}
GuiBase.getInterface().showImageDialog(image, displayName + " (" + type + ")\n" + desc, "Achievement Earned");
}
return value;
}
public final boolean needSave() {
return best != defaultValue;
}
public void saveToXml(final Element el) {
el.setAttribute("best", String.valueOf(best));
el.setAttribute("time", String.valueOf(timestamp));
}
public void loadFromXml(final Element el) {
best = XmlUtil.getIntAttribute(el, "best");
timestamp = XmlUtil.getLongAttribute(el, "time");
best = performConversion(best, timestamp);
}
//give derived classes a chance to perform a conversion if needed
protected int performConversion(final int value, final long timestamp) {
return value;
}
protected abstract String getNoun();
protected boolean pluralizeNoun() {
return best != 1;
}
protected boolean displayNounBefore() {
return false;
}
protected final String getFormattedTimestamp() {
if (timestamp == 0) { return null; }
final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
return formatter.format(new Date(timestamp));
}
public String getSubTitle(final boolean includeTimestamp) {
if (best == defaultValue) { return null; }
String subTitle;
if (displayNounBefore()) {
subTitle = "Best: " + getNoun() + " " + best;
}
else {
subTitle = "Best: " + best + " " + (pluralizeNoun() ? Lang.getPlural(getNoun()) : getNoun());
}
if (includeTimestamp) {
final String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
subTitle += " (" + formattedTimestamp + ")";
}
}
return subTitle;
}
}
package forge.achievement;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.w3c.dom.Element;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.properties.ForgeConstants;
import forge.util.Lang;
import forge.util.XmlUtil;
public abstract class Achievement {
private final String key, displayName, sharedDesc, commonDesc, uncommonDesc, rareDesc, mythicDesc;
private final int commonThreshold, uncommonThreshold, rareThreshold, mythicThreshold;
private final boolean checkGreaterThan;
protected final int defaultValue;
private ISkinImage image;
private long timestamp;
private int best;
//use this constructor for special achievements without tiers
protected Achievement(final String key0, final String displayName0, final String description0, final String flavorText0, final int defaultValue0) {
this(key0, displayName0, description0, defaultValue0, null, 1, null, 1, null, 1, "(" + flavorText0 + ")", 1); //pass flavor text as mythic description so it appears below description faded out
}
//use this constructor for regular tiered achievements
protected Achievement(final String key0, final String displayName0, final String sharedDesc0, final int defaultValue0,
final String commonDesc0, final int commonThreshold0,
final String uncommonDesc0, final int uncommonThreshold0,
final String rareDesc0, final int rareThreshold0,
final String mythicDesc0, final int mythicThreshold0) {
key = key0;
displayName = displayName0;
sharedDesc = sharedDesc0;
commonDesc = commonDesc0;
commonThreshold = commonThreshold0;
uncommonDesc = uncommonDesc0;
uncommonThreshold = uncommonThreshold0;
rareDesc = rareDesc0;
rareThreshold = rareThreshold0;
mythicDesc = mythicDesc0;
mythicThreshold = mythicThreshold0;
checkGreaterThan = rareThreshold0 >= uncommonThreshold0;
best = defaultValue0;
defaultValue = defaultValue0;
}
public String getKey() {
return key;
}
public String getDisplayName() {
return displayName;
}
public String getSharedDesc() {
return sharedDesc;
}
public String getCommonDesc() {
return commonDesc;
}
public String getUncommonDesc() {
return uncommonDesc;
}
public String getRareDesc() {
return rareDesc;
}
public String getMythicDesc() {
return mythicDesc;
}
public ISkinImage getImage() {
if (image == null) {
updateTrophyImage();
}
return image;
}
public int getBest() {
return best;
}
public boolean isSpecial() {
return mythicThreshold == commonThreshold;
}
private boolean earnedSpecial() {
return (isSpecial() && best > 0);
}
public boolean earnedMythic() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= mythicThreshold;
}
return best <= mythicThreshold;
}
public boolean earnedRare() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= rareThreshold;
}
return best <= rareThreshold;
}
public boolean earnedUncommon() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= uncommonThreshold;
}
return best <= uncommonThreshold;
}
public boolean earnedCommon() {
if (isSpecial()) { return false; }
if (checkGreaterThan) {
return best >= commonThreshold;
}
return best <= commonThreshold;
}
//get card associated with this achievement if any
public IPaperCard getPaperCard() {
return null;
}
protected abstract int evaluate(Player player, Game game);
private void updateTrophyImage() {
FSkinProp background;
float opacity = 1;
if (earnedSpecial()) {
background = FSkinProp.IMG_SPECIAL_TROPHY;
}
else if (earnedMythic()) {
background = FSkinProp.IMG_MYTHIC_TROPHY;
}
else if (earnedRare()) {
background = FSkinProp.IMG_RARE_TROPHY;
}
else if (earnedUncommon()) {
background = FSkinProp.IMG_UNCOMMON_TROPHY;
}
else if (earnedCommon()) {
background = FSkinProp.IMG_COMMON_TROPHY;
}
else {
opacity = 0.25f; //fade out if achievement hasn't been earned yet
if (mythicThreshold == commonThreshold) {
background = FSkinProp.IMG_SPECIAL_TROPHY;
}
else {
background = FSkinProp.IMG_COMMON_TROPHY;
}
}
image = GuiBase.getInterface().createLayeredImage(background, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + key + ".png", opacity);
}
public int update(final Player player) {
final int value = evaluate(player, player.getGame());
if (checkGreaterThan) {
if (value <= best) { return value; }
}
else if (value >= best) { return value; }
final boolean hadEarnedSpecial = earnedSpecial();
final boolean hadEarnedMythic = earnedMythic();
final boolean hadEarnedRare = earnedRare();
final boolean hadEarnedUncommon = earnedUncommon();
final boolean hadEarnedCommon = earnedCommon();
best = value;
timestamp = new Date().getTime();
if (earnedSpecial()) {
if (!hadEarnedSpecial) {
updateTrophyImage();
GuiBase.getInterface().showImageDialog(image, displayName + "\n" + sharedDesc + "\n" + mythicDesc, "Achievement Earned");
}
return value;
}
String type = null;
String desc = null;
if (earnedMythic()) {
if (!hadEarnedMythic) {
type = "Mythic";
desc = mythicDesc;
}
}
else if (earnedRare()) {
if (!hadEarnedRare) {
type = "Rare";
desc = rareDesc;
}
}
else if (earnedUncommon()) {
if (!hadEarnedUncommon) {
type = "Uncommon";
desc = uncommonDesc;
}
}
else if (earnedCommon()) {
if (!hadEarnedCommon) {
type = "Common";
desc = commonDesc;
}
}
if (type != null) {
updateTrophyImage();
if (sharedDesc != null) {
desc = sharedDesc + " " + desc;
}
GuiBase.getInterface().showImageDialog(image, displayName + " (" + type + ")\n" + desc, "Achievement Earned");
}
return value;
}
public final boolean needSave() {
return best != defaultValue;
}
public void saveToXml(final Element el) {
el.setAttribute("best", String.valueOf(best));
el.setAttribute("time", String.valueOf(timestamp));
}
public void loadFromXml(final Element el) {
best = XmlUtil.getIntAttribute(el, "best");
timestamp = XmlUtil.getLongAttribute(el, "time");
best = performConversion(best, timestamp);
}
//give derived classes a chance to perform a conversion if needed
protected int performConversion(final int value, final long timestamp) {
return value;
}
protected abstract String getNoun();
protected boolean pluralizeNoun() {
return best != 1;
}
protected boolean displayNounBefore() {
return false;
}
protected final String getFormattedTimestamp() {
if (timestamp == 0) { return null; }
final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
return formatter.format(new Date(timestamp));
}
public String getSubTitle(final boolean includeTimestamp) {
if (best == defaultValue) { return null; }
String subTitle;
if (displayNounBefore()) {
subTitle = "Best: " + getNoun() + " " + best;
}
else {
subTitle = "Best: " + best + " " + (pluralizeNoun() ? Lang.getPlural(getNoun()) : getNoun());
}
if (includeTimestamp) {
final String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
subTitle += " (" + formattedTimestamp + ")";
}
}
return subTitle;
}
}

View File

@@ -1,209 +1,209 @@
package forge.achievement;
import forge.GuiBase;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.interfaces.IComboBox;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.ThreadUtil;
import forge.util.XmlUtil;
public abstract class AchievementCollection implements Iterable<Achievement> {
protected final Map<String, Achievement> achievements = Maps.newLinkedHashMap();
protected final String name, filename, path;
protected final boolean isLimitedFormat;
static {
FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR);
}
public static void updateAll(final PlayerControllerHuman controller) {
//don't update achievements if player cheated during game
if (controller.hasCheated()) {
return;
}
final Game game = controller.getGame();
final Player player = controller.getPlayer();
//update all achievements for GUI player after game finished
//(we are doing it in different threads in different game ports to prevent freezing when processing multiple achievements)
if (GuiBase.getInterface().isLibgdxPort()) {
ThreadUtil.invokeInGameThread(new Runnable() {
@Override
public void run() {
doUpdateAllAchievements(game, player);
}
});
} else {
doUpdateAllAchievements(game, player);
}
}
private static void doUpdateAllAchievements(final Game game, final Player player) {
FModel.getAchievements(game.getRules().getGameType()).updateAll(player);
AltWinAchievements.instance.updateAll(player);
PlaneswalkerAchievements.instance.updateAll(player);
ChallengeAchievements.instance.updateAll(player);
}
public static void buildComboBox(IComboBox<AchievementCollection> cb) {
cb.addItem(FModel.getAchievements(GameType.Constructed));
cb.addItem(FModel.getAchievements(GameType.Draft));
cb.addItem(FModel.getAchievements(GameType.Sealed));
cb.addItem(FModel.getAchievements(GameType.Quest));
cb.addItem(FModel.getAchievements(GameType.PlanarConquest));
cb.addItem(FModel.getAchievements(GameType.Puzzle));
cb.addItem(AltWinAchievements.instance);
cb.addItem(PlaneswalkerAchievements.instance);
cb.addItem(ChallengeAchievements.instance);
}
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) {
this(name0, filename0, isLimitedFormat0, (String) null);
}
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0, String path0) {
name = name0;
filename = filename0;
isLimitedFormat = isLimitedFormat0;
path = path0;
addSharedAchivements();
addAchievements();
load();
}
protected void addSharedAchivements() {
add(new GameWinStreak(10, 25, 50, 100));
add(new MatchWinStreak(10, 25, 50, 100));
add(new TotalGameWins(250, 500, 1000, 2000));
add(new TotalMatchWins(100, 250, 500, 1000));
if (isLimitedFormat) { //make need for speed goal more realistic for limited formats
add(new NeedForSpeed(8, 6, 4, 2));
}
else {
add(new NeedForSpeed(5, 3, 1, 0));
}
add(new Overkill(-25, -50, -100, -200));
add(new LifeToSpare(20, 40, 80, 160));
add(new Hellbent());
add(new ArcaneMaster());
add(new StormChaser(5, 10, 20, 50));
add(new ManaScrewed());
if (isLimitedFormat) { //lower gold and mythic thresholds based on smaller decks
add(new ManaFlooded(8, 11, 14, 17));
}
else {
add(new ManaFlooded(8, 12, 18, 24));
}
add(new RagsToRiches());
}
protected void addAchievements() {
if (path != null) {
final List<String> achievementListFile = FileUtil.readFile(path);
for (final String s : achievementListFile) {
if (!s.isEmpty()) {
String k[] = StringUtils.split(s, "|");
add(k[0],k[1],k[2]);
}
}
}
}
protected void add(Achievement achievement) {
achievements.put(achievement.getKey(), achievement);
}
protected void add(String name, String title, String desc) {
// to overwrite
}
public void updateAll(Player player) {
for (Achievement achievement : achievements.values()) {
achievement.update(player);
}
save();
}
public void load() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(filename));
final NodeList nodes = document.getElementsByTagName("a");
for (int i = 0; i < nodes.getLength(); i++) {
final Element el = (Element)nodes.item(i);
final Achievement achievement = achievements.get(el.getAttribute("name"));
if (achievement != null) {
achievement.loadFromXml(el);
}
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
protected void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("achievements");
document.appendChild(root);
for (Entry<String, Achievement> entry : achievements.entrySet()) {
Achievement achievement = entry.getValue();
if (achievement.needSave()) {
Element el = document.createElement("a");
el.setAttribute("name", entry.getKey());
achievement.saveToXml(el);
root.appendChild(el);
}
}
XmlUtil.saveDocument(document, filename);
}
catch (Exception e) {
e.printStackTrace();
}
}
public int getCount() {
return achievements.size();
}
/* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Achievement> iterator() {
return achievements.values().iterator();
}
@Override
public String toString() {
return name;
}
}
package forge.achievement;
import forge.GuiBase;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.google.common.collect.Maps;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.interfaces.IComboBox;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.ThreadUtil;
import forge.util.XmlUtil;
public abstract class AchievementCollection implements Iterable<Achievement> {
protected final Map<String, Achievement> achievements = Maps.newLinkedHashMap();
protected final String name, filename, path;
protected final boolean isLimitedFormat;
static {
FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR);
}
public static void updateAll(final PlayerControllerHuman controller) {
//don't update achievements if player cheated during game
if (controller.hasCheated()) {
return;
}
final Game game = controller.getGame();
final Player player = controller.getPlayer();
//update all achievements for GUI player after game finished
//(we are doing it in different threads in different game ports to prevent freezing when processing multiple achievements)
if (GuiBase.getInterface().isLibgdxPort()) {
ThreadUtil.invokeInGameThread(new Runnable() {
@Override
public void run() {
doUpdateAllAchievements(game, player);
}
});
} else {
doUpdateAllAchievements(game, player);
}
}
private static void doUpdateAllAchievements(final Game game, final Player player) {
FModel.getAchievements(game.getRules().getGameType()).updateAll(player);
AltWinAchievements.instance.updateAll(player);
PlaneswalkerAchievements.instance.updateAll(player);
ChallengeAchievements.instance.updateAll(player);
}
public static void buildComboBox(IComboBox<AchievementCollection> cb) {
cb.addItem(FModel.getAchievements(GameType.Constructed));
cb.addItem(FModel.getAchievements(GameType.Draft));
cb.addItem(FModel.getAchievements(GameType.Sealed));
cb.addItem(FModel.getAchievements(GameType.Quest));
cb.addItem(FModel.getAchievements(GameType.PlanarConquest));
cb.addItem(FModel.getAchievements(GameType.Puzzle));
cb.addItem(AltWinAchievements.instance);
cb.addItem(PlaneswalkerAchievements.instance);
cb.addItem(ChallengeAchievements.instance);
}
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) {
this(name0, filename0, isLimitedFormat0, (String) null);
}
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0, String path0) {
name = name0;
filename = filename0;
isLimitedFormat = isLimitedFormat0;
path = path0;
addSharedAchivements();
addAchievements();
load();
}
protected void addSharedAchivements() {
add(new GameWinStreak(10, 25, 50, 100));
add(new MatchWinStreak(10, 25, 50, 100));
add(new TotalGameWins(250, 500, 1000, 2000));
add(new TotalMatchWins(100, 250, 500, 1000));
if (isLimitedFormat) { //make need for speed goal more realistic for limited formats
add(new NeedForSpeed(8, 6, 4, 2));
}
else {
add(new NeedForSpeed(5, 3, 1, 0));
}
add(new Overkill(-25, -50, -100, -200));
add(new LifeToSpare(20, 40, 80, 160));
add(new Hellbent());
add(new ArcaneMaster());
add(new StormChaser(5, 10, 20, 50));
add(new ManaScrewed());
if (isLimitedFormat) { //lower gold and mythic thresholds based on smaller decks
add(new ManaFlooded(8, 11, 14, 17));
}
else {
add(new ManaFlooded(8, 12, 18, 24));
}
add(new RagsToRiches());
}
protected void addAchievements() {
if (path != null) {
final List<String> achievementListFile = FileUtil.readFile(path);
for (final String s : achievementListFile) {
if (!s.isEmpty()) {
String k[] = StringUtils.split(s, "|");
add(k[0],k[1],k[2]);
}
}
}
}
protected void add(Achievement achievement) {
achievements.put(achievement.getKey(), achievement);
}
protected void add(String name, String title, String desc) {
// to overwrite
}
public void updateAll(Player player) {
for (Achievement achievement : achievements.values()) {
achievement.update(player);
}
save();
}
public void load() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(filename));
final NodeList nodes = document.getElementsByTagName("a");
for (int i = 0; i < nodes.getLength(); i++) {
final Element el = (Element)nodes.item(i);
final Achievement achievement = achievements.get(el.getAttribute("name"));
if (achievement != null) {
achievement.loadFromXml(el);
}
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
protected void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("achievements");
document.appendChild(root);
for (Entry<String, Achievement> entry : achievements.entrySet()) {
Achievement achievement = entry.getValue();
if (achievement.needSave()) {
Element el = document.createElement("a");
el.setAttribute("name", entry.getKey());
achievement.saveToXml(el);
root.appendChild(el);
}
}
XmlUtil.saveDocument(document, filename);
}
catch (Exception e) {
e.printStackTrace();
}
}
public int getCount() {
return achievements.size();
}
/* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Achievement> iterator() {
return achievements.values().iterator();
}
@Override
public String toString() {
return name;
}
}

View File

@@ -1,70 +1,70 @@
package forge.achievement;
import org.apache.commons.lang3.StringUtils;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
public class AltWinAchievements extends AchievementCollection {
public static final AltWinAchievements instance = new AltWinAchievements();
private AltWinAchievements() {
super("Alternate Win Conditions", ForgeConstants.ACHIEVEMENTS_DIR + "altwin.xml", false, ForgeConstants.ALTWIN_ACHIEVEMENT_LIST_FILE);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
protected void add(String cardName0, String displayName0, String flavorText0) {
add(new AltWinAchievement(cardName0, displayName0, flavorText0));
}
@Override
public void updateAll(Player player) {
//only call update achievement for alternate win condition (if any)
if (player.getOutcome().hasWon()) {
String altWinCondition = player.getOutcome().altWinSourceName;
if (StringUtils.isEmpty(altWinCondition)) {
Player opponent = player.getSingleOpponent();
if (opponent == null) { return; }
altWinCondition = opponent.getOutcome().loseConditionSpell;
if (StringUtils.isEmpty(altWinCondition)) {
return;
}
}
Achievement achievement = achievements.get(altWinCondition);
if (achievement != null) {
achievement.update(player);
save();
}
}
}
private class AltWinAchievement extends ProgressiveAchievement {
private AltWinAchievement(String cardName0, String displayName0, String flavorText0) {
super(cardName0, displayName0, "Win a game with " + cardName0, flavorText0);
}
@Override
protected boolean eval(Player player, Game game) {
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
}
@Override
public IPaperCard getPaperCard() {
return FModel.getMagicDb().getCommonCards().getCard(getKey());
}
@Override
public String getNoun() {
return "Win";
}
}
}
package forge.achievement;
import org.apache.commons.lang3.StringUtils;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
public class AltWinAchievements extends AchievementCollection {
public static final AltWinAchievements instance = new AltWinAchievements();
private AltWinAchievements() {
super("Alternate Win Conditions", ForgeConstants.ACHIEVEMENTS_DIR + "altwin.xml", false, ForgeConstants.ALTWIN_ACHIEVEMENT_LIST_FILE);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
protected void add(String cardName0, String displayName0, String flavorText0) {
add(new AltWinAchievement(cardName0, displayName0, flavorText0));
}
@Override
public void updateAll(Player player) {
//only call update achievement for alternate win condition (if any)
if (player.getOutcome().hasWon()) {
String altWinCondition = player.getOutcome().altWinSourceName;
if (StringUtils.isEmpty(altWinCondition)) {
Player opponent = player.getSingleOpponent();
if (opponent == null) { return; }
altWinCondition = opponent.getOutcome().loseConditionSpell;
if (StringUtils.isEmpty(altWinCondition)) {
return;
}
}
Achievement achievement = achievements.get(altWinCondition);
if (achievement != null) {
achievement.update(player);
save();
}
}
}
private class AltWinAchievement extends ProgressiveAchievement {
private AltWinAchievement(String cardName0, String displayName0, String flavorText0) {
super(cardName0, displayName0, "Win a game with " + cardName0, flavorText0);
}
@Override
protected boolean eval(Player player, Game game) {
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
}
@Override
public IPaperCard getPaperCard() {
return FModel.getMagicDb().getCommonCards().getCard(getKey());
}
@Override
public String getNoun() {
return "Win";
}
}
}

View File

@@ -1,31 +1,31 @@
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
public class ArcaneMaster extends Achievement {
public ArcaneMaster() {
super("ArcaneMaster", "Arcane Master", "Win a game without casting", Integer.MAX_VALUE,
"more than 3 spells", 3,
"more than 2 spells", 2,
"more than 1 spell", 1,
"any spells", 0);
}
@Override
protected int evaluate(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
return defaultValue; // Momir Basic is exempt from this achievement (custom rules do not require any spellcasting by default)
}
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().spellsCast;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Spell";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
public class ArcaneMaster extends Achievement {
public ArcaneMaster() {
super("ArcaneMaster", "Arcane Master", "Win a game without casting", Integer.MAX_VALUE,
"more than 3 spells", 3,
"more than 2 spells", 2,
"more than 1 spell", 1,
"any spells", 0);
}
@Override
protected int evaluate(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
return defaultValue; // Momir Basic is exempt from this achievement (custom rules do not require any spellcasting by default)
}
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().spellsCast;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Spell";
}
}

View File

@@ -1,50 +1,50 @@
package forge.achievement;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class Blackjack extends Achievement {
private static final int THRESHOLD = 21;
public Blackjack(int silver0, int gold0, int mythic0) {
super("Blackjack", "Blackjack", "Win a game from your commander dealing", 0,
String.format("%d combat damage", THRESHOLD), THRESHOLD,
String.format("%d combat damage", silver0), silver0,
String.format("%d combat damage", gold0), gold0,
String.format("%d combat damage", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
for (Player p : game.getRegisteredPlayers()) {
if (p.isOpponentOf(player) && p.getOutcome().lossState == GameLossReason.CommanderDamage) {
int max = 0;
for (Card c : player.getCommanders()) {
Integer damage = p.getCommanderDamage(c);
if (damage != null && damage >= THRESHOLD) {
max = damage;
return damage;
}
}
if (max > 0) {
return max;
}
}
}
}
return 0;
}
@Override
public String getNoun() {
return "Damage";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class Blackjack extends Achievement {
private static final int THRESHOLD = 21;
public Blackjack(int silver0, int gold0, int mythic0) {
super("Blackjack", "Blackjack", "Win a game from your commander dealing", 0,
String.format("%d combat damage", THRESHOLD), THRESHOLD,
String.format("%d combat damage", silver0), silver0,
String.format("%d combat damage", gold0), gold0,
String.format("%d combat damage", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
for (Player p : game.getRegisteredPlayers()) {
if (p.isOpponentOf(player) && p.getOutcome().lossState == GameLossReason.CommanderDamage) {
int max = 0;
for (Card c : player.getCommanders()) {
Integer damage = p.getCommanderDamage(c);
if (damage != null && damage >= THRESHOLD) {
max = damage;
return damage;
}
}
if (max > 0) {
return max;
}
}
}
}
return 0;
}
@Override
public String getNoun() {
return "Damage";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
}

View File

@@ -1,82 +1,82 @@
package forge.achievement;
import forge.deck.Deck;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.properties.ForgeConstants;
public class ChallengeAchievements extends AchievementCollection {
public static final ChallengeAchievements instance = new ChallengeAchievements();
private ChallengeAchievements() {
super("Challenges", ForgeConstants.ACHIEVEMENTS_DIR + "challenges.xml", false);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
@Override
protected void addAchievements() {
add(new NoCreatures());
add(new NoSpells());
add(new NoLands());
add(new Domain());
add("Chromatic", "Chromatic", "Win a game after casting a 5 color spell", "With great color requirements comes great power.");
add("Epic", "Epic", "Win a game after resolving a spell with the Epic keyword", "When it's the last spell you ever cast, you better make it count!");
}
private void add(String key0, String displayName0, String description0, String flavorText0) {
add(new ChallengeAchievement(key0, displayName0, description0, flavorText0));
}
public static class ChallengeAchievement extends ProgressiveAchievement {
protected ChallengeAchievement(String key0, String displayName0, String description0, String flavorText0) {
super(key0, displayName0, description0, flavorText0);
}
@Override
protected final String getNoun() {
return "Win";
}
@Override
protected boolean eval(Player player, Game game) {
if (!ChallengeAchievements.checkValidGameMode(game)) {
return false;
}
return player.getOutcome().hasWon() &&
player.getAchievementTracker().challengesCompleted.contains(getKey());
}
}
public static abstract class DeckChallengeAchievement extends ChallengeAchievement {
protected DeckChallengeAchievement(String key0, String displayName0, String condition0, String flavorText0) {
super(key0, displayName0, "Win a game using a deck " + condition0, flavorText0);
}
@Override
protected final boolean eval(Player player, Game game) {
if (!ChallengeAchievements.checkValidGameMode(game)) {
return false;
}
if (player.getOutcome().hasWon()) {
return eval(player.getRegisteredPlayer().getDeck());
}
return false;
}
protected abstract boolean eval(Deck deck);
}
public static boolean checkValidGameMode(final Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)
|| game.getRules().hasAppliedVariant(GameType.Puzzle)) {
// these modes use a fixed pre-defined deck format, so challenge achievements don't apply in them
return false;
}
return true;
}
}
package forge.achievement;
import forge.deck.Deck;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.properties.ForgeConstants;
public class ChallengeAchievements extends AchievementCollection {
public static final ChallengeAchievements instance = new ChallengeAchievements();
private ChallengeAchievements() {
super("Challenges", ForgeConstants.ACHIEVEMENTS_DIR + "challenges.xml", false);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
@Override
protected void addAchievements() {
add(new NoCreatures());
add(new NoSpells());
add(new NoLands());
add(new Domain());
add("Chromatic", "Chromatic", "Win a game after casting a 5 color spell", "With great color requirements comes great power.");
add("Epic", "Epic", "Win a game after resolving a spell with the Epic keyword", "When it's the last spell you ever cast, you better make it count!");
}
private void add(String key0, String displayName0, String description0, String flavorText0) {
add(new ChallengeAchievement(key0, displayName0, description0, flavorText0));
}
public static class ChallengeAchievement extends ProgressiveAchievement {
protected ChallengeAchievement(String key0, String displayName0, String description0, String flavorText0) {
super(key0, displayName0, description0, flavorText0);
}
@Override
protected final String getNoun() {
return "Win";
}
@Override
protected boolean eval(Player player, Game game) {
if (!ChallengeAchievements.checkValidGameMode(game)) {
return false;
}
return player.getOutcome().hasWon() &&
player.getAchievementTracker().challengesCompleted.contains(getKey());
}
}
public static abstract class DeckChallengeAchievement extends ChallengeAchievement {
protected DeckChallengeAchievement(String key0, String displayName0, String condition0, String flavorText0) {
super(key0, displayName0, "Win a game using a deck " + condition0, flavorText0);
}
@Override
protected final boolean eval(Player player, Game game) {
if (!ChallengeAchievements.checkValidGameMode(game)) {
return false;
}
if (player.getOutcome().hasWon()) {
return eval(player.getRegisteredPlayer().getDeck());
}
return false;
}
protected abstract boolean eval(Deck deck);
}
public static boolean checkValidGameMode(final Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)
|| game.getRules().hasAppliedVariant(GameType.Puzzle)) {
// these modes use a fixed pre-defined deck format, so challenge achievements don't apply in them
return false;
}
return true;
}
}

View File

@@ -1,24 +1,24 @@
package forge.achievement;
import forge.game.GameType;
import forge.properties.ForgeConstants;
public class ConstructedAchievements extends AchievementCollection {
public ConstructedAchievements() {
super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
add(new VariantWins(GameType.Vanguard, 25, 50, 100));
add(new VariantWins(GameType.MomirBasic, 25, 50, 100));
add(new VariantWins(GameType.Commander, 25, 50, 100));
add(new VariantWins(GameType.TinyLeaders, 25, 50, 100));
add(new VariantWins(GameType.Planechase, 25, 50, 100));
add(new VariantWins(GameType.Archenemy, 25, 50, 100));
add(new Poisoned(15, 25, 40));
add(new DeckedOut(8, 4, 2));
add(new Blackjack(30, 50, 100));
}
}
package forge.achievement;
import forge.game.GameType;
import forge.properties.ForgeConstants;
public class ConstructedAchievements extends AchievementCollection {
public ConstructedAchievements() {
super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
add(new VariantWins(GameType.Vanguard, 25, 50, 100));
add(new VariantWins(GameType.MomirBasic, 25, 50, 100));
add(new VariantWins(GameType.Commander, 25, 50, 100));
add(new VariantWins(GameType.TinyLeaders, 25, 50, 100));
add(new VariantWins(GameType.Planechase, 25, 50, 100));
add(new VariantWins(GameType.Archenemy, 25, 50, 100));
add(new Poisoned(15, 25, 40));
add(new DeckedOut(8, 4, 2));
add(new Blackjack(30, 50, 100));
}
}

View File

@@ -1,36 +1,36 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class DeckedOut extends Achievement {
public DeckedOut(int silver0, int gold0, int mythic0) {
super("DeckedOut", "Decked Out", "Win a game from opponent", Integer.MAX_VALUE,
"drawing into an empty library", Integer.MAX_VALUE - 1,
String.format("drawing into an empty library by turn %d", silver0), silver0,
String.format("drawing into an empty library by turn %d", gold0), gold0,
String.format("drawing into an empty library by turn %d", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) {
return player.getTurn();
}
}
return Integer.MAX_VALUE;
}
@Override
protected String getNoun() {
return "Turn";
}
@Override
protected boolean displayNounBefore() {
return true;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class DeckedOut extends Achievement {
public DeckedOut(int silver0, int gold0, int mythic0) {
super("DeckedOut", "Decked Out", "Win a game from opponent", Integer.MAX_VALUE,
"drawing into an empty library", Integer.MAX_VALUE - 1,
String.format("drawing into an empty library by turn %d", silver0), silver0,
String.format("drawing into an empty library by turn %d", gold0), gold0,
String.format("drawing into an empty library by turn %d", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) {
return player.getTurn();
}
}
return Integer.MAX_VALUE;
}
@Override
protected String getNoun() {
return "Turn";
}
@Override
protected boolean displayNounBefore() {
return true;
}
}

View File

@@ -1,39 +1,39 @@
package forge.achievement;
import java.util.HashSet;
import java.util.Set;
import forge.game.Game;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class Domain extends ProgressiveAchievement {
public Domain() {
super("Domain", "Domain", "Win a game with one of each basic land on the battlefield", "It's nice being able to cast anything you want.");
}
@Override
protected boolean eval(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
// Not an achievement in Momir Basic (easy to get due to predefined deck contents)
return false;
}
if (player.getOutcome().hasWon()) {
Set<String> basicLands = new HashSet<String>();
for (Card c : player.getCardsIn(ZoneType.Battlefield)) {
if (c.isBasicLand()) {
basicLands.add(c.getName());
}
}
return basicLands.size() == 5;
}
return false;
}
@Override
protected String getNoun() {
return "Win";
}
}
package forge.achievement;
import java.util.HashSet;
import java.util.Set;
import forge.game.Game;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class Domain extends ProgressiveAchievement {
public Domain() {
super("Domain", "Domain", "Win a game with one of each basic land on the battlefield", "It's nice being able to cast anything you want.");
}
@Override
protected boolean eval(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
// Not an achievement in Momir Basic (easy to get due to predefined deck contents)
return false;
}
if (player.getOutcome().hasWon()) {
Set<String> basicLands = new HashSet<String>();
for (Card c : player.getCardsIn(ZoneType.Battlefield)) {
if (c.isBasicLand()) {
basicLands.add(c.getName());
}
}
return basicLands.size() == 5;
}
return false;
}
@Override
protected String getNoun() {
return "Win";
}
}

View File

@@ -1,14 +1,14 @@
package forge.achievement;
import forge.properties.ForgeConstants;
public class DraftAchievements extends AchievementCollection {
public DraftAchievements() {
super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
}
}
package forge.achievement;
import forge.properties.ForgeConstants;
public class DraftAchievements extends AchievementCollection {
public DraftAchievements() {
super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
}
}

View File

@@ -1,19 +1,19 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class GameWinStreak extends StreakAchievement {
public GameWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
super("GameWinStreak", "Game Win Streak", null,
String.format("Win %d games in a row", bronze0), bronze0,
String.format("Win %d games in a row", silver0), silver0,
String.format("Win %d games in a row", gold0), gold0,
String.format("Win %d games in a row", mythic0), mythic0);
}
@Override
protected Boolean eval(Player player, Game game) {
return player.getOutcome().hasWon();
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class GameWinStreak extends StreakAchievement {
public GameWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
super("GameWinStreak", "Game Win Streak", null,
String.format("Win %d games in a row", bronze0), bronze0,
String.format("Win %d games in a row", silver0), silver0,
String.format("Win %d games in a row", gold0), gold0,
String.format("Win %d games in a row", mythic0), mythic0);
}
@Override
protected Boolean eval(Player player, Game game) {
return player.getOutcome().hasWon();
}
}

View File

@@ -1,50 +1,50 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class Hellbent extends Achievement {
public Hellbent() {
super("Hellbent", "Hellbent", "Win a game with no cards in your", 0,
"hand", 1,
"hand or library", 2,
"hand, library, or graveyard", 3,
"hand, library, graveyard, or battlefield", 4);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
if (player.getZone(ZoneType.Hand).size() == 0) {
if (player.getZone(ZoneType.Library).size() == 0) {
if (player.getZone(ZoneType.Graveyard).size() == 0) {
if (player.getZone(ZoneType.Battlefield).size() == 0) {
return 4;
}
return 3;
}
return 2;
}
return 1;
}
}
return 0;
}
@Override
protected String getNoun() {
return null;
}
@Override
public String getSubTitle(boolean includeTimestamp) {
if (includeTimestamp) {
String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
return "Earned " + formattedTimestamp;
}
}
return null;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class Hellbent extends Achievement {
public Hellbent() {
super("Hellbent", "Hellbent", "Win a game with no cards in your", 0,
"hand", 1,
"hand or library", 2,
"hand, library, or graveyard", 3,
"hand, library, graveyard, or battlefield", 4);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
if (player.getZone(ZoneType.Hand).size() == 0) {
if (player.getZone(ZoneType.Library).size() == 0) {
if (player.getZone(ZoneType.Graveyard).size() == 0) {
if (player.getZone(ZoneType.Battlefield).size() == 0) {
return 4;
}
return 3;
}
return 2;
}
return 1;
}
}
return 0;
}
@Override
protected String getNoun() {
return null;
}
@Override
public String getSubTitle(boolean includeTimestamp) {
if (includeTimestamp) {
String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
return "Earned " + formattedTimestamp;
}
}
return null;
}
}

View File

@@ -1,34 +1,34 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class LifeToSpare extends Achievement {
public LifeToSpare(int bronze0, int silver0, int gold0, int mythic0) {
super("LifeToSpare", "Life to Spare", "Win a game with", 0,
String.format("%d life more than you started with", bronze0), bronze0,
String.format("%d life more than you started with", silver0), silver0,
String.format("%d life more than you started with", gold0), gold0,
String.format("%d life more than you started with", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
int gainedLife = player.getLife() - player.getStartingLife();
if (gainedLife > 0) {
return gainedLife;
}
}
return 0;
}
@Override
protected String getNoun() {
return "Life";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class LifeToSpare extends Achievement {
public LifeToSpare(int bronze0, int silver0, int gold0, int mythic0) {
super("LifeToSpare", "Life to Spare", "Win a game with", 0,
String.format("%d life more than you started with", bronze0), bronze0,
String.format("%d life more than you started with", silver0), silver0,
String.format("%d life more than you started with", gold0), gold0,
String.format("%d life more than you started with", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
int gainedLife = player.getLife() - player.getStartingLife();
if (gainedLife > 0) {
return gainedLife;
}
}
return 0;
}
@Override
protected String getNoun() {
return "Life";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
}

View File

@@ -1,39 +1,39 @@
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class ManaFlooded extends Achievement {
public ManaFlooded(int bronze0, int silver0, int gold0, int mythic0) {
super("ManaFlooded", "Mana Flooded", "Win a game with at least", 0,
String.format("%d lands on the battlefield", bronze0), bronze0,
String.format("%d lands on the battlefield", silver0), silver0,
String.format("%d lands on the battlefield", gold0), gold0,
String.format("%d lands on the battlefield", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
return 0; // in Momir Basic, getting a lot of lands out is not an achievement:w
}
if (player.getOutcome().hasWon()) {
int landCount = 0;
for (Card c : player.getZone(ZoneType.Battlefield).getCards()) {
if (c.isLand()) {
landCount++;
}
}
return landCount;
}
return 0; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Land";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class ManaFlooded extends Achievement {
public ManaFlooded(int bronze0, int silver0, int gold0, int mythic0) {
super("ManaFlooded", "Mana Flooded", "Win a game with at least", 0,
String.format("%d lands on the battlefield", bronze0), bronze0,
String.format("%d lands on the battlefield", silver0), silver0,
String.format("%d lands on the battlefield", gold0), gold0,
String.format("%d lands on the battlefield", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
return 0; // in Momir Basic, getting a lot of lands out is not an achievement:w
}
if (player.getOutcome().hasWon()) {
int landCount = 0;
for (Card c : player.getZone(ZoneType.Battlefield).getCards()) {
if (c.isLand()) {
landCount++;
}
}
return landCount;
}
return 0; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Land";
}
}

View File

@@ -1,37 +1,37 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class ManaScrewed extends Achievement {
public ManaScrewed() {
super("ManaScrewed", "Mana Screwed", "Win a game despite playing only", Integer.MAX_VALUE,
"3 lands", 3,
"2 lands", 2,
"1 land", 1,
"0 lands", 0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().landsPlayed;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Land";
}
@Override
protected int performConversion(int value, long timestamp) {
//throw out any ManaScrewed achievements earned before timestamp support added
//since there was a bug where it was earned almost always
if (timestamp == 0) {
return defaultValue;
}
return value;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class ManaScrewed extends Achievement {
public ManaScrewed() {
super("ManaScrewed", "Mana Screwed", "Win a game despite playing only", Integer.MAX_VALUE,
"3 lands", 3,
"2 lands", 2,
"1 land", 1,
"0 lands", 0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().landsPlayed;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Land";
}
@Override
protected int performConversion(int value, long timestamp) {
//throw out any ManaScrewed achievements earned before timestamp support added
//since there was a bug where it was earned almost always
if (timestamp == 0) {
return defaultValue;
}
return value;
}
}

View File

@@ -1,25 +1,25 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class MatchWinStreak extends StreakAchievement {
public MatchWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
super("MatchWinStreak", "Match Win Streak", null,
String.format("Win %d matches in a row", bronze0), bronze0,
String.format("Win %d matches in a row", silver0), silver0,
String.format("Win %d matches in a row", gold0), gold0,
String.format("Win %d matches in a row", mythic0), mythic0);
}
@Override
protected Boolean eval(Player player, Game game) {
if (game.getMatch().isMatchOver()) {
if (game.getMatch().isWonBy(player.getLobbyPlayer())) {
return true;
}
return false;
}
return null;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class MatchWinStreak extends StreakAchievement {
public MatchWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
super("MatchWinStreak", "Match Win Streak", null,
String.format("Win %d matches in a row", bronze0), bronze0,
String.format("Win %d matches in a row", silver0), silver0,
String.format("Win %d matches in a row", gold0), gold0,
String.format("Win %d matches in a row", mythic0), mythic0);
}
@Override
protected Boolean eval(Player player, Game game) {
if (game.getMatch().isMatchOver()) {
if (game.getMatch().isWonBy(player.getLobbyPlayer())) {
return true;
}
return false;
}
return null;
}
}

View File

@@ -1,32 +1,32 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class NeedForSpeed extends Achievement {
public NeedForSpeed(int bronze0, int silver0, int gold0, int mythic0) {
super("NeedForSpeed", "Need for Speed", null, Integer.MAX_VALUE,
String.format("Win a game by turn %d", bronze0), bronze0,
String.format("Win a game by turn %d", silver0), silver0,
String.format("Win a game by turn %d", gold0), gold0,
String.format("Win a game by turn %d", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getTurn();
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Turn";
}
@Override
protected boolean displayNounBefore() {
return true;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class NeedForSpeed extends Achievement {
public NeedForSpeed(int bronze0, int silver0, int gold0, int mythic0) {
super("NeedForSpeed", "Need for Speed", null, Integer.MAX_VALUE,
String.format("Win a game by turn %d", bronze0), bronze0,
String.format("Win a game by turn %d", silver0), silver0,
String.format("Win a game by turn %d", gold0), gold0,
String.format("Win a game by turn %d", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getTurn();
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Turn";
}
@Override
protected boolean displayNounBefore() {
return true;
}
}

View File

@@ -1,23 +1,23 @@
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoCreatures extends DeckChallengeAchievement {
public NoCreatures() {
super("NoCreatures", "No Creatures", "with no creatures", "I'm not really an animal person.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
if (card.getKey().getRules().getType().isCreature()) {
return false;
}
}
return true;
}
}
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoCreatures extends DeckChallengeAchievement {
public NoCreatures() {
super("NoCreatures", "No Creatures", "with no creatures", "I'm not really an animal person.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
if (card.getKey().getRules().getType().isCreature()) {
return false;
}
}
return true;
}
}

View File

@@ -1,23 +1,23 @@
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoLands extends DeckChallengeAchievement {
public NoLands() {
super("NoLands", "No Lands", "with no lands", "I prefer mana from more artificial sources.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
if (card.getKey().getRules().getType().isLand()) {
return false;
}
}
return true;
}
}
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoLands extends DeckChallengeAchievement {
public NoLands() {
super("NoLands", "No Lands", "with no lands", "I prefer mana from more artificial sources.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
if (card.getKey().getRules().getType().isLand()) {
return false;
}
}
return true;
}
}

View File

@@ -1,25 +1,25 @@
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.card.CardType;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoSpells extends DeckChallengeAchievement {
public NoSpells() {
super("NoSpells", "No Spells", "with only creatures and lands", "I let my army do the talking.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
CardType type = card.getKey().getRules().getType();
if (!type.isCreature() && !type.isLand()) {
return false;
}
}
return true;
}
}
package forge.achievement;
import java.util.Map.Entry;
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
import forge.card.CardType;
import forge.deck.Deck;
import forge.item.PaperCard;
public class NoSpells extends DeckChallengeAchievement {
public NoSpells() {
super("NoSpells", "No Spells", "with only creatures and lands", "I let my army do the talking.");
}
@Override
protected boolean eval(Deck deck) {
for (Entry<PaperCard, Integer> card : deck.getMain()) {
CardType type = card.getKey().getRules().getType();
if (!type.isCreature() && !type.isLand()) {
return false;
}
}
return true;
}
}

View File

@@ -1,43 +1,43 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class Overkill extends Achievement {
public Overkill(int bronze0, int silver0, int gold0, int mythic0) {
super("Overkill", "Overkill", "Win a game with opponent at", 0,
String.format("%d life", bronze0), bronze0,
String.format("%d life", silver0), silver0,
String.format("%d life", gold0), gold0,
String.format("%d life", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getLife() < 0) {
return opponent.getLife();
}
}
return 0;
}
@Override
protected String getNoun() {
return "Life";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
@Override
protected int performConversion(int value, long timestamp) {
//perform conversion to handle data from old format before supporting negative thresholds
if (value > 0) {
value = -value;
}
return value;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class Overkill extends Achievement {
public Overkill(int bronze0, int silver0, int gold0, int mythic0) {
super("Overkill", "Overkill", "Win a game with opponent at", 0,
String.format("%d life", bronze0), bronze0,
String.format("%d life", silver0), silver0,
String.format("%d life", gold0), gold0,
String.format("%d life", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getLife() < 0) {
return opponent.getLife();
}
}
return 0;
}
@Override
protected String getNoun() {
return "Life";
}
@Override
protected boolean pluralizeNoun() {
return false;
}
@Override
protected int performConversion(int value, long timestamp) {
//perform conversion to handle data from old format before supporting negative thresholds
if (value > 0) {
value = -value;
}
return value;
}
}

View File

@@ -1,70 +1,70 @@
package forge.achievement;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
public class PlaneswalkerAchievements extends AchievementCollection {
public static final PlaneswalkerAchievements instance = new PlaneswalkerAchievements();
public static ISkinImage getTrophyImage(String planeswalkerName) {
return GuiBase.getInterface().createLayeredImage(FSkinProp.IMG_SPECIAL_TROPHY, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + planeswalkerName + ".png", 1);
}
private PlaneswalkerAchievements() {
super("Planeswalker Ultimates", ForgeConstants.ACHIEVEMENTS_DIR + "planeswalkers.xml", false, ForgeConstants.PLANESWALKER_ACHIEVEMENT_LIST_FILE);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
protected void add(String cardName0, String displayName0, String flavorText0) {
add(new PlaneswalkerUltimate(cardName0, displayName0, flavorText0));
}
@Override
public void updateAll(Player player) {
//only call update achievements for any ultimates activated during the game
if (player.getOutcome().hasWon()) {
boolean needSave = false;
for (String ultimate : player.getAchievementTracker().activatedUltimates) {
Achievement achievement = achievements.get(ultimate);
if (achievement != null) {
achievement.update(player);
needSave = true;
}
}
if (needSave) {
save();
}
}
}
private class PlaneswalkerUltimate extends ProgressiveAchievement {
private PlaneswalkerUltimate(String cardName0, String displayName0, String flavorText0) {
super(cardName0, displayName0, "Win a game after activating " + cardName0 + "'s ultimate", flavorText0);
}
@Override
protected boolean eval(Player player, Game game) {
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
}
@Override
public IPaperCard getPaperCard() {
return FModel.getMagicDb().getCommonCards().getCard(getKey());
}
@Override
protected String getNoun() {
return "Win";
}
}
}
package forge.achievement;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.game.Game;
import forge.game.player.Player;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
public class PlaneswalkerAchievements extends AchievementCollection {
public static final PlaneswalkerAchievements instance = new PlaneswalkerAchievements();
public static ISkinImage getTrophyImage(String planeswalkerName) {
return GuiBase.getInterface().createLayeredImage(FSkinProp.IMG_SPECIAL_TROPHY, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + planeswalkerName + ".png", 1);
}
private PlaneswalkerAchievements() {
super("Planeswalker Ultimates", ForgeConstants.ACHIEVEMENTS_DIR + "planeswalkers.xml", false, ForgeConstants.PLANESWALKER_ACHIEVEMENT_LIST_FILE);
}
@Override
protected void addSharedAchivements() {
//prevent including shared achievements
}
protected void add(String cardName0, String displayName0, String flavorText0) {
add(new PlaneswalkerUltimate(cardName0, displayName0, flavorText0));
}
@Override
public void updateAll(Player player) {
//only call update achievements for any ultimates activated during the game
if (player.getOutcome().hasWon()) {
boolean needSave = false;
for (String ultimate : player.getAchievementTracker().activatedUltimates) {
Achievement achievement = achievements.get(ultimate);
if (achievement != null) {
achievement.update(player);
needSave = true;
}
}
if (needSave) {
save();
}
}
}
private class PlaneswalkerUltimate extends ProgressiveAchievement {
private PlaneswalkerUltimate(String cardName0, String displayName0, String flavorText0) {
super(cardName0, displayName0, "Win a game after activating " + cardName0 + "'s ultimate", flavorText0);
}
@Override
protected boolean eval(Player player, Game game) {
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
}
@Override
public IPaperCard getPaperCard() {
return FModel.getMagicDb().getCommonCards().getCard(getKey());
}
@Override
protected String getNoun() {
return "Win";
}
}
}

View File

@@ -1,33 +1,33 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class Poisoned extends Achievement {
private static final int THRESHOLD = 10;
public Poisoned(int silver0, int gold0, int mythic0) {
super("Poisoned", "Poisoned", "Win a game by giving opponent", 0,
String.format("%d poison counters", THRESHOLD), THRESHOLD,
String.format("%d poison counters", silver0), silver0,
String.format("%d poison counters", gold0), gold0,
String.format("%d poison counters", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) {
return opponent.getPoisonCounters();
}
}
return 0;
}
@Override
protected String getNoun() {
return "Counter";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.GameLossReason;
import forge.game.player.Player;
public class Poisoned extends Achievement {
private static final int THRESHOLD = 10;
public Poisoned(int silver0, int gold0, int mythic0) {
super("Poisoned", "Poisoned", "Win a game by giving opponent", 0,
String.format("%d poison counters", THRESHOLD), THRESHOLD,
String.format("%d poison counters", silver0), silver0,
String.format("%d poison counters", gold0), gold0,
String.format("%d poison counters", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) {
return opponent.getPoisonCounters();
}
}
return 0;
}
@Override
protected String getNoun() {
return "Counter";
}
}

View File

@@ -1,43 +1,43 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
import forge.util.Lang;
public abstract class ProgressiveAchievement extends Achievement {
protected ProgressiveAchievement(String key0, String displayName0, String description0, String flavorText0) {
super(key0, displayName0, description0, flavorText0, 0);
}
//use this constructor for regular tiered achievements
protected ProgressiveAchievement(String key0, String displayName0, String sharedDesc0,
String commonDesc0, int commonThreshold0,
String uncommonDesc0, int uncommonThreshold0,
String rareDesc0, int rareThreshold0,
String mythicDesc0, int mythicThreshold0) {
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
mythicDesc0, mythicThreshold0);
}
protected abstract boolean eval(Player player, Game game);
@Override
protected final int evaluate(Player player, Game game) {
if (eval(player, game)) {
return getBest() + 1;
}
return getBest();
}
@Override
public final String getSubTitle(boolean includeTimestamp) {
String subTitle = getBest() + " " + (getBest() != 1 ? Lang.getPlural(getNoun()) : getNoun());
if (includeTimestamp) {
String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
subTitle += " (" + formattedTimestamp + ")";
}
}
return subTitle;
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
import forge.util.Lang;
public abstract class ProgressiveAchievement extends Achievement {
protected ProgressiveAchievement(String key0, String displayName0, String description0, String flavorText0) {
super(key0, displayName0, description0, flavorText0, 0);
}
//use this constructor for regular tiered achievements
protected ProgressiveAchievement(String key0, String displayName0, String sharedDesc0,
String commonDesc0, int commonThreshold0,
String uncommonDesc0, int uncommonThreshold0,
String rareDesc0, int rareThreshold0,
String mythicDesc0, int mythicThreshold0) {
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
mythicDesc0, mythicThreshold0);
}
protected abstract boolean eval(Player player, Game game);
@Override
protected final int evaluate(Player player, Game game) {
if (eval(player, game)) {
return getBest() + 1;
}
return getBest();
}
@Override
public final String getSubTitle(boolean includeTimestamp) {
String subTitle = getBest() + " " + (getBest() != 1 ? Lang.getPlural(getNoun()) : getNoun());
if (includeTimestamp) {
String formattedTimestamp = getFormattedTimestamp();
if (formattedTimestamp != null) {
subTitle += " (" + formattedTimestamp + ")";
}
}
return subTitle;
}
}

View File

@@ -1,16 +1,16 @@
package forge.achievement;
import forge.properties.ForgeConstants;
public class QuestAchievements extends AchievementCollection {
public QuestAchievements() {
super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
add(new Poisoned(15, 25, 40));
add(new DeckedOut(8, 4, 2));
}
}
package forge.achievement;
import forge.properties.ForgeConstants;
public class QuestAchievements extends AchievementCollection {
public QuestAchievements() {
super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
add(new Poisoned(15, 25, 40));
add(new DeckedOut(8, 4, 2));
}
}

View File

@@ -1,27 +1,27 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class RagsToRiches extends Achievement {
public RagsToRiches() {
super("RagsToRiches", "Rags to Riches", "Win a game after mulliganing to", 7,
"4 cards", 4,
"3 cards", 3,
"2 cards", 2,
"1 card", 1);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon() && player.getAchievementTracker().mulliganTo < defaultValue) {
return player.getAchievementTracker().mulliganTo;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Card";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class RagsToRiches extends Achievement {
public RagsToRiches() {
super("RagsToRiches", "Rags to Riches", "Win a game after mulliganing to", 7,
"4 cards", 4,
"3 cards", 3,
"2 cards", 2,
"1 card", 1);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon() && player.getAchievementTracker().mulliganTo < defaultValue) {
return player.getAchievementTracker().mulliganTo;
}
return defaultValue; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Card";
}
}

View File

@@ -1,14 +1,14 @@
package forge.achievement;
import forge.properties.ForgeConstants;
public class SealedAchievements extends AchievementCollection {
public SealedAchievements() {
super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
}
}
package forge.achievement;
import forge.properties.ForgeConstants;
public class SealedAchievements extends AchievementCollection {
public SealedAchievements() {
super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true);
}
//add achievements that should appear at the bottom below core achievements for each game mode
@Override
protected void addAchievements() {
}
}

View File

@@ -1,27 +1,27 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class StormChaser extends Achievement {
public StormChaser(int bronze0, int silver0, int gold0, int mythic0) {
super("StormChaser", "Storm Chaser", "Win a game after casting", 0,
String.format("%d spells in a single turn", bronze0), bronze0,
String.format("%d spells in a single turn", silver0), silver0,
String.format("%d spells in a single turn", gold0), gold0,
String.format("%d spells in a single turn", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().maxStormCount;
}
return 0; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Spell";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class StormChaser extends Achievement {
public StormChaser(int bronze0, int silver0, int gold0, int mythic0) {
super("StormChaser", "Storm Chaser", "Win a game after casting", 0,
String.format("%d spells in a single turn", bronze0), bronze0,
String.format("%d spells in a single turn", silver0), silver0,
String.format("%d spells in a single turn", gold0), gold0,
String.format("%d spells in a single turn", mythic0), mythic0);
}
@Override
protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) {
return player.getAchievementTracker().maxStormCount;
}
return 0; //indicate that player didn't win
}
@Override
protected String getNoun() {
return "Spell";
}
}

View File

@@ -1,59 +1,59 @@
package forge.achievement;
import org.w3c.dom.Element;
import forge.game.Game;
import forge.game.player.Player;
import forge.util.XmlUtil;
public abstract class StreakAchievement extends Achievement {
private int current;
//use this constructor for regular tiered achievements
protected StreakAchievement(final String key0, final String displayName0, final String sharedDesc0,
final String commonDesc0, final int commonThreshold0,
final String uncommonDesc0, final int uncommonThreshold0,
final String rareDesc0, final int rareThreshold0,
final String mythicDesc0, final int mythicThreshold0) {
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
mythicDesc0, mythicThreshold0);
}
protected abstract Boolean eval(Player player, Game game);
@Override
protected final int evaluate(final Player player, final Game game) {
final Boolean val = eval(player, game);
if (val != null) { //null means don't increment or reset
if (val) {
current++;
}
else {
current = 0;
}
}
return current;
}
@Override
protected String getNoun() {
return "Active: " + current; //override here so active streak appears after best
}
@Override
protected boolean pluralizeNoun() {
return false;
}
@Override
public void saveToXml(final Element el) {
super.saveToXml(el);
el.setAttribute("current", String.valueOf(current));
}
@Override
public void loadFromXml(final Element el) {
super.loadFromXml(el);
current = XmlUtil.getIntAttribute(el, "current");
}
}
package forge.achievement;
import org.w3c.dom.Element;
import forge.game.Game;
import forge.game.player.Player;
import forge.util.XmlUtil;
public abstract class StreakAchievement extends Achievement {
private int current;
//use this constructor for regular tiered achievements
protected StreakAchievement(final String key0, final String displayName0, final String sharedDesc0,
final String commonDesc0, final int commonThreshold0,
final String uncommonDesc0, final int uncommonThreshold0,
final String rareDesc0, final int rareThreshold0,
final String mythicDesc0, final int mythicThreshold0) {
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
mythicDesc0, mythicThreshold0);
}
protected abstract Boolean eval(Player player, Game game);
@Override
protected final int evaluate(final Player player, final Game game) {
final Boolean val = eval(player, game);
if (val != null) { //null means don't increment or reset
if (val) {
current++;
}
else {
current = 0;
}
}
return current;
}
@Override
protected String getNoun() {
return "Active: " + current; //override here so active streak appears after best
}
@Override
protected boolean pluralizeNoun() {
return false;
}
@Override
public void saveToXml(final Element el) {
super.saveToXml(el);
el.setAttribute("current", String.valueOf(current));
}
@Override
public void loadFromXml(final Element el) {
super.loadFromXml(el);
current = XmlUtil.getIntAttribute(el, "current");
}
}

View File

@@ -1,24 +1,24 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class TotalGameWins extends ProgressiveAchievement {
public TotalGameWins(int bronze0, int silver0, int gold0, int mythic0) {
super("TotalGameWins", "Total Game Wins", null,
String.format("Win %d games", bronze0), bronze0,
String.format("Win %d games", silver0), silver0,
String.format("Win %d games", gold0), gold0,
String.format("Win %d games", mythic0), mythic0);
}
@Override
protected boolean eval(Player player, Game game) {
return player.getOutcome().hasWon();
}
@Override
protected String getNoun() {
return "Game";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class TotalGameWins extends ProgressiveAchievement {
public TotalGameWins(int bronze0, int silver0, int gold0, int mythic0) {
super("TotalGameWins", "Total Game Wins", null,
String.format("Win %d games", bronze0), bronze0,
String.format("Win %d games", silver0), silver0,
String.format("Win %d games", gold0), gold0,
String.format("Win %d games", mythic0), mythic0);
}
@Override
protected boolean eval(Player player, Game game) {
return player.getOutcome().hasWon();
}
@Override
protected String getNoun() {
return "Game";
}
}

View File

@@ -1,24 +1,24 @@
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class TotalMatchWins extends ProgressiveAchievement {
public TotalMatchWins(int bronze0, int silver0, int gold0, int mythic0) {
super("TotalMatchWins", "Total Match Wins", null,
String.format("Win %d matches", bronze0), bronze0,
String.format("Win %d matches", silver0), silver0,
String.format("Win %d matches", gold0), gold0,
String.format("Win %d matches", mythic0), mythic0);
}
@Override
protected boolean eval(Player player, Game game) {
return game.getMatch().isMatchOver() && game.getMatch().isWonBy(player.getLobbyPlayer());
}
@Override
protected String getNoun() {
return "Match";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.player.Player;
public class TotalMatchWins extends ProgressiveAchievement {
public TotalMatchWins(int bronze0, int silver0, int gold0, int mythic0) {
super("TotalMatchWins", "Total Match Wins", null,
String.format("Win %d matches", bronze0), bronze0,
String.format("Win %d matches", silver0), silver0,
String.format("Win %d matches", gold0), gold0,
String.format("Win %d matches", mythic0), mythic0);
}
@Override
protected boolean eval(Player player, Game game) {
return game.getMatch().isMatchOver() && game.getMatch().isWonBy(player.getLobbyPlayer());
}
@Override
protected String getNoun() {
return "Match";
}
}

View File

@@ -1,37 +1,37 @@
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.util.Lang;
public class VariantWins extends ProgressiveAchievement {
private GameType variant;
public VariantWins(GameType variant0, int silver0, int gold0, int mythic0) {
super(variant0.name(), variant0.toString(), null,
"Win " + Lang.nounWithAmount(1, variant0.toString() + " game"), 1,
"Win " + Lang.nounWithAmount(silver0, variant0.toString() + " game"), silver0,
"Win " + Lang.nounWithAmount(gold0, variant0.toString() + " game"), gold0,
"Win " + Lang.nounWithAmount(mythic0, variant0.toString() + " game"), mythic0);
variant = variant0;
}
@Override
protected boolean eval(Player player, Game game) {
if (player.getOutcome().hasWon()) {
if (game.getRules().hasAppliedVariant(variant)) {
return true;
}
if (variant == GameType.Archenemy && game.getRules().hasAppliedVariant(GameType.ArchenemyRumble)) {
return true; //lump Archenemy Rumble into same achievement as Archenemy
}
}
return false;
}
@Override
protected String getNoun() {
return "Win";
}
}
package forge.achievement;
import forge.game.Game;
import forge.game.GameType;
import forge.game.player.Player;
import forge.util.Lang;
public class VariantWins extends ProgressiveAchievement {
private GameType variant;
public VariantWins(GameType variant0, int silver0, int gold0, int mythic0) {
super(variant0.name(), variant0.toString(), null,
"Win " + Lang.nounWithAmount(1, variant0.toString() + " game"), 1,
"Win " + Lang.nounWithAmount(silver0, variant0.toString() + " game"), silver0,
"Win " + Lang.nounWithAmount(gold0, variant0.toString() + " game"), gold0,
"Win " + Lang.nounWithAmount(mythic0, variant0.toString() + " game"), mythic0);
variant = variant0;
}
@Override
protected boolean eval(Player player, Game game) {
if (player.getOutcome().hasWon()) {
if (game.getRules().hasAppliedVariant(variant)) {
return true;
}
if (variant == GameType.Archenemy && game.getRules().hasAppliedVariant(GameType.ArchenemyRumble)) {
return true; //lump Archenemy Rumble into same achievement as Archenemy
}
}
return false;
}
@Override
protected String getNoun() {
return "Win";
}
}

View File

@@ -1,5 +1,5 @@
package forge.assets;
public interface IHasSkinProp {
FSkinProp getSkinProp();
}
package forge.assets;
public interface IHasSkinProp {
FSkinProp getSkinProp();
}

View File

@@ -1,5 +1,5 @@
package forge.assets;
public interface ISkinImage {
}
package forge.assets;
public interface ISkinImage {
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,120 +1,120 @@
package forge.card;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual cards
*
*/
public class CardPreferences {
private static Map<String, CardPreferences> allPrefs = new HashMap<String, CardPreferences>();
public static CardPreferences getPrefs(IPaperCard card) {
String cardName = card.getName();
CardPreferences prefs = allPrefs.get(cardName);
if (prefs == null) {
prefs = new CardPreferences(cardName);
allPrefs.put(cardName, prefs);
}
return prefs;
}
public static void load() {
allPrefs.clear();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.CARD_PREFS_FILE));
final NodeList cards = document.getElementsByTagName("card");
for (int i = 0; i < cards.getLength(); i++) {
final Element el = (Element)cards.item(i);
final CardPreferences prefs = new CardPreferences(el.getAttribute("name"));
allPrefs.put(prefs.cardName, prefs);
prefs.setStarCount(XmlUtil.getIntAttribute(el, "stars"));
prefs.setPreferredArt(XmlUtil.getStringAttribute(el, "art"));
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "cards");
document.appendChild(root);
for (Map.Entry<String, CardPreferences> entry : allPrefs.entrySet()) {
CardPreferences prefs = entry.getValue();
if (prefs.starCount > 0 || prefs.preferredArt != null) {
Element card = document.createElement("card");
card.setAttribute("name", entry.getKey());
if (prefs.starCount > 0) {
card.setAttribute("stars", String.valueOf(prefs.starCount));
}
if (prefs.preferredArt != null) {
card.setAttribute("art", prefs.preferredArt);
}
root.appendChild(card);
}
}
XmlUtil.saveDocument(document, ForgeConstants.CARD_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
private final String cardName;
private int starCount;
private String preferredArt;
private CardPreferences(String cardName0) {
cardName = cardName0;
}
public int getStarCount() {
return starCount;
}
public void setStarCount(int starCount0) {
starCount = starCount0;
}
public String getPreferredArt() {
return preferredArt;
}
public void setPreferredArt(String preferredArt0) {
if (preferredArt0 == null) {
preferredArt = null;
return;
}
if (preferredArt0.equals(preferredArt)) { return; }
if (FModel.getMagicDb().getCommonCards().setPreferredArt(cardName, preferredArt0)) {
preferredArt = preferredArt0;
}
}
package forge.card;
import forge.item.IPaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual cards
*
*/
public class CardPreferences {
private static Map<String, CardPreferences> allPrefs = new HashMap<String, CardPreferences>();
public static CardPreferences getPrefs(IPaperCard card) {
String cardName = card.getName();
CardPreferences prefs = allPrefs.get(cardName);
if (prefs == null) {
prefs = new CardPreferences(cardName);
allPrefs.put(cardName, prefs);
}
return prefs;
}
public static void load() {
allPrefs.clear();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.CARD_PREFS_FILE));
final NodeList cards = document.getElementsByTagName("card");
for (int i = 0; i < cards.getLength(); i++) {
final Element el = (Element)cards.item(i);
final CardPreferences prefs = new CardPreferences(el.getAttribute("name"));
allPrefs.put(prefs.cardName, prefs);
prefs.setStarCount(XmlUtil.getIntAttribute(el, "stars"));
prefs.setPreferredArt(XmlUtil.getStringAttribute(el, "art"));
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "cards");
document.appendChild(root);
for (Map.Entry<String, CardPreferences> entry : allPrefs.entrySet()) {
CardPreferences prefs = entry.getValue();
if (prefs.starCount > 0 || prefs.preferredArt != null) {
Element card = document.createElement("card");
card.setAttribute("name", entry.getKey());
if (prefs.starCount > 0) {
card.setAttribute("stars", String.valueOf(prefs.starCount));
}
if (prefs.preferredArt != null) {
card.setAttribute("art", prefs.preferredArt);
}
root.appendChild(card);
}
}
XmlUtil.saveDocument(document, ForgeConstants.CARD_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
private final String cardName;
private int starCount;
private String preferredArt;
private CardPreferences(String cardName0) {
cardName = cardName0;
}
public int getStarCount() {
return starCount;
}
public void setStarCount(int starCount0) {
starCount = starCount0;
}
public String getPreferredArt() {
return preferredArt;
}
public void setPreferredArt(String preferredArt0) {
if (preferredArt0 == null) {
preferredArt = null;
return;
}
if (preferredArt0.equals(preferredArt)) { return; }
if (FModel.getMagicDb().getCommonCards().setPreferredArt(cardName, preferredArt0)) {
preferredArt = preferredArt0;
}
}
}

View File

@@ -1,194 +1,194 @@
package forge.card;
import forge.CardStorageReader;
import forge.card.CardRules;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CardReaderExperiments {
//utility functions to parse all cards and perform certain actions on each card
public static void parseAllCards(String[] args) {
if (args.length < 2) { return; }
int totalParsedCount = 0;
final List<List<String>> output = new ArrayList<List<String>>();
for (int i = 1; i < args.length; i++) {
output.add(new ArrayList<String>());
}
final List<File> allFiles = CardStorageReader.collectCardFiles(new ArrayList<File>(), new File(ForgeConstants.CARD_DATA_DIR));
Charset charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
final CardRules.Reader rulesReader = new CardRules.Reader();
for (File file : allFiles) {
rulesReader.reset();
InputStreamReader isr;
try {
isr = new InputStreamReader(new FileInputStream(file), charset);
List<String> lines = FileUtil.readAllLines(isr, true);
CardRules rules = rulesReader.readCard(lines);
System.out.println();
System.out.print(rules.getName()); //print each card here in case it gets stuck in utility
totalParsedCount++;
for (int i = 1; i < args.length; i++) {
switch (args[i]) {
case "updateAbilityManaSymbols":
updateAbilityManaSymbols(rules, lines, file, output.get(i - 1));
break;
}
}
}
catch (FileNotFoundException ex) {
}
}
System.out.println();
System.out.println();
System.out.print("Total cards: " + totalParsedCount);
for (int i = 1; i < args.length; i++) {
List<String> singleOutput = output.get(i - 1);
System.out.println();
System.out.println();
System.out.println(args[i] + ":");
System.out.println();
for (String line : singleOutput) {
System.out.println(line);
}
System.out.println();
System.out.print("Total cards: " + singleOutput.size());
}
}
private static void updateAbilityManaSymbols(CardRules rules, List<String> lines, File file, List<String> output) {
boolean updated = false;
//ensure mana symbols appear in correct order
String wubrg = "WUBRG";
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i);
for (int c = 0; c < 5; c++) {
char ch1 = wubrg.charAt(c);
char ch2 = wubrg.charAt((c + 1) % 5);
char ch3 = wubrg.charAt((c + 2) % 5);
newLine = newLine.replaceAll("(^|\\W)(" + ch2 + "|" + ch3 + ")( ?)(/?)" + ch1 + "(\\W|$)", "$1" + ch1 + "$3$4$2$5");
newLine = newLine.replaceAll("(^|\\W)\\{(" + ch2 + "|" + ch3 + ")\\}\\{" + ch1 + "\\}(\\W|$)", "$1\\{" + ch1 + "\\}\\{$2\\}$3");
}
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
i--; //if something changed, repeat in case more than 2 mana symbols consecutively
}
}
//convert {2W} and {PW} to {2/W} and {P/W}, and ensure not {W/2} or {W/P}
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i).replaceAll("\\{([WUBRG2P])([WUBRG])\\}", "\\{$1/$2\\}")
.replaceAll("\\{([WUBRG])/2\\}", "\\{2/$1\\}")
.replaceAll("\\{([WUBRG])/P\\}", "\\{P/$1\\}");
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
}
}
//check for oracle text appearing in ability descriptions missing "{G}" formatting
if (updated) { //if lines updated above, ensure updated oracle text used
rules = CardRules.fromScript(lines);
}
String oracleText = rules.getOracleText();
String[] sentences = oracleText.replace(rules.getName(), "CARDNAME").split("\\.|\\\\n|\\\"|\\(|\\)");
for (String s : sentences) {
int idx = s.indexOf(":");
if (idx != -1) {
s = s.substring(idx + 1);
}
if (s.isEmpty()) { continue; }
try {
String pattern = s.replaceAll("\\{([WUBRGSXYZ]|[0-9]+)\\}", "$1[ ]\\?")
.replaceAll("\\{([WUBRG2P])/([WUBRG])\\}", "$1$2[ ]\\?")
.replaceAll("\\{C\\}", "Chaos");
if (pattern.length() != s.length()) {
pattern = "Description\\$(.*)" + pattern;
s = "Description\\$$1" + s;
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i).replaceAll(pattern, s);
if (newLine.length() != lines.get(i).length()) {
updated = true;
lines.set(i, newLine);
}
}
}
}
catch (Exception ex) {
output.add("<Exception (" + rules.getName() + ") " + ex.getMessage() + ">");
return;
}
}
//convert mana costs in quoted ability descriptions
//TODO: Uncomment when not flawed (currently doesn't work with hybrid, consecutive symbols, "Untap" in place of Q, or Pay # life/Put +1/+1 or -1/-1 costs
/*for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i)
.replaceAll("Description\\$(.*)\\\"(.*)Tap:(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}:$3\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)Tap([ ,][A-Z0-9\\{].*):(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}$3:$4\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}:$4\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+)([ ,].*):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}$4:$5\\\"");
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
}
}*/
//check for other key phrases that might be missing "{G}" formatting
String[] phrases = new String[] {
"Add * to your mana pool",
"CostDesc\\$ * \\|"
};
for (String phrase : phrases) {
String pattern = ".*" + phrase.replace("* ", "((([WUBRGSXYZ]|[0-9]+) )+)") + ".*";
Pattern p = Pattern.compile(pattern);
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
Matcher m = p.matcher(line);
if (m.matches()) {
StringBuilder newLineBuilder = new StringBuilder();
newLineBuilder.append(line.substring(0, m.start(1)));
for (String sym : m.group(1).split(" ")) {
newLineBuilder.append("{" + sym + "}");
}
newLineBuilder.append(line.substring(m.end(1) - 1)); //-1 so final space appended
updated = true;
lines.set(i, newLineBuilder.toString());
}
}
}
if (updated) {
try {
PrintWriter p = new PrintWriter(file);
for (int i = 0; i < lines.size(); i++) {
if (i < lines.size() - 1) {
p.println(lines.get(i));
}
else {
p.print(lines.get(i));
}
}
p.close();
output.add(rules.getName());
} catch (final Exception ex) {
}
}
}
package forge.card;
import forge.CardStorageReader;
import forge.card.CardRules;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CardReaderExperiments {
//utility functions to parse all cards and perform certain actions on each card
public static void parseAllCards(String[] args) {
if (args.length < 2) { return; }
int totalParsedCount = 0;
final List<List<String>> output = new ArrayList<List<String>>();
for (int i = 1; i < args.length; i++) {
output.add(new ArrayList<String>());
}
final List<File> allFiles = CardStorageReader.collectCardFiles(new ArrayList<File>(), new File(ForgeConstants.CARD_DATA_DIR));
Charset charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
final CardRules.Reader rulesReader = new CardRules.Reader();
for (File file : allFiles) {
rulesReader.reset();
InputStreamReader isr;
try {
isr = new InputStreamReader(new FileInputStream(file), charset);
List<String> lines = FileUtil.readAllLines(isr, true);
CardRules rules = rulesReader.readCard(lines);
System.out.println();
System.out.print(rules.getName()); //print each card here in case it gets stuck in utility
totalParsedCount++;
for (int i = 1; i < args.length; i++) {
switch (args[i]) {
case "updateAbilityManaSymbols":
updateAbilityManaSymbols(rules, lines, file, output.get(i - 1));
break;
}
}
}
catch (FileNotFoundException ex) {
}
}
System.out.println();
System.out.println();
System.out.print("Total cards: " + totalParsedCount);
for (int i = 1; i < args.length; i++) {
List<String> singleOutput = output.get(i - 1);
System.out.println();
System.out.println();
System.out.println(args[i] + ":");
System.out.println();
for (String line : singleOutput) {
System.out.println(line);
}
System.out.println();
System.out.print("Total cards: " + singleOutput.size());
}
}
private static void updateAbilityManaSymbols(CardRules rules, List<String> lines, File file, List<String> output) {
boolean updated = false;
//ensure mana symbols appear in correct order
String wubrg = "WUBRG";
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i);
for (int c = 0; c < 5; c++) {
char ch1 = wubrg.charAt(c);
char ch2 = wubrg.charAt((c + 1) % 5);
char ch3 = wubrg.charAt((c + 2) % 5);
newLine = newLine.replaceAll("(^|\\W)(" + ch2 + "|" + ch3 + ")( ?)(/?)" + ch1 + "(\\W|$)", "$1" + ch1 + "$3$4$2$5");
newLine = newLine.replaceAll("(^|\\W)\\{(" + ch2 + "|" + ch3 + ")\\}\\{" + ch1 + "\\}(\\W|$)", "$1\\{" + ch1 + "\\}\\{$2\\}$3");
}
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
i--; //if something changed, repeat in case more than 2 mana symbols consecutively
}
}
//convert {2W} and {PW} to {2/W} and {P/W}, and ensure not {W/2} or {W/P}
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i).replaceAll("\\{([WUBRG2P])([WUBRG])\\}", "\\{$1/$2\\}")
.replaceAll("\\{([WUBRG])/2\\}", "\\{2/$1\\}")
.replaceAll("\\{([WUBRG])/P\\}", "\\{P/$1\\}");
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
}
}
//check for oracle text appearing in ability descriptions missing "{G}" formatting
if (updated) { //if lines updated above, ensure updated oracle text used
rules = CardRules.fromScript(lines);
}
String oracleText = rules.getOracleText();
String[] sentences = oracleText.replace(rules.getName(), "CARDNAME").split("\\.|\\\\n|\\\"|\\(|\\)");
for (String s : sentences) {
int idx = s.indexOf(":");
if (idx != -1) {
s = s.substring(idx + 1);
}
if (s.isEmpty()) { continue; }
try {
String pattern = s.replaceAll("\\{([WUBRGSXYZ]|[0-9]+)\\}", "$1[ ]\\?")
.replaceAll("\\{([WUBRG2P])/([WUBRG])\\}", "$1$2[ ]\\?")
.replaceAll("\\{C\\}", "Chaos");
if (pattern.length() != s.length()) {
pattern = "Description\\$(.*)" + pattern;
s = "Description\\$$1" + s;
for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i).replaceAll(pattern, s);
if (newLine.length() != lines.get(i).length()) {
updated = true;
lines.set(i, newLine);
}
}
}
}
catch (Exception ex) {
output.add("<Exception (" + rules.getName() + ") " + ex.getMessage() + ">");
return;
}
}
//convert mana costs in quoted ability descriptions
//TODO: Uncomment when not flawed (currently doesn't work with hybrid, consecutive symbols, "Untap" in place of Q, or Pay # life/Put +1/+1 or -1/-1 costs
/*for (int i = 0; i < lines.size(); i++) {
String newLine = lines.get(i)
.replaceAll("Description\\$(.*)\\\"(.*)Tap:(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}:$3\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)Tap([ ,][A-Z0-9\\{].*):(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}$3:$4\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}:$4\\\"")
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+)([ ,].*):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}$4:$5\\\"");
if (!newLine.equals(lines.get(i))) {
updated = true;
lines.set(i, newLine);
}
}*/
//check for other key phrases that might be missing "{G}" formatting
String[] phrases = new String[] {
"Add * to your mana pool",
"CostDesc\\$ * \\|"
};
for (String phrase : phrases) {
String pattern = ".*" + phrase.replace("* ", "((([WUBRGSXYZ]|[0-9]+) )+)") + ".*";
Pattern p = Pattern.compile(pattern);
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
Matcher m = p.matcher(line);
if (m.matches()) {
StringBuilder newLineBuilder = new StringBuilder();
newLineBuilder.append(line.substring(0, m.start(1)));
for (String sym : m.group(1).split(" ")) {
newLineBuilder.append("{" + sym + "}");
}
newLineBuilder.append(line.substring(m.end(1) - 1)); //-1 so final space appended
updated = true;
lines.set(i, newLineBuilder.toString());
}
}
}
if (updated) {
try {
PrintWriter p = new PrintWriter(file);
for (int i = 0; i < lines.size(); i++) {
if (i < lines.size() - 1) {
p.println(lines.get(i));
}
else {
p.print(lines.get(i));
}
}
p.close();
output.add(rules.getName());
} catch (final Exception ex) {
}
}
}
}

View File

@@ -1,81 +1,81 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card;
import java.io.File;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
public final class CardScriptInfo {
private String text;
private final File file;
public CardScriptInfo(final String text0, final File file0) {
text = text0;
file = file0;
}
public String getText() {
return text;
}
public File getFile() {
return file;
}
public boolean canEdit() {
return file != null;
}
public boolean trySetText(final String text0) {
if (file == null) { return false; }
try {
final PrintWriter p = new PrintWriter(file);
p.print(text0);
p.close();
text = text0;
return true;
}
catch (final Exception ex) {
System.err.println("Problem writing file - " + file);
ex.printStackTrace();
return false;
}
}
private static Map<String, CardScriptInfo> allScripts = new ConcurrentHashMap<>();
public static CardScriptInfo getScriptFor(final String name) {
CardScriptInfo script = allScripts.get(name);
if (script == null) { //attempt to load script if not previously loaded
final String filename = name.toLowerCase().replace(' ', '_').replace('-', '_').replace("'", "").replace(",", "") + ".txt";
final File file = new File(ForgeConstants.CARD_DATA_DIR + filename.charAt(0) + File.separator + filename);
if (file.exists()) {
script = new CardScriptInfo(FileUtil.readFileToString(file), file);
allScripts.put(name, script);
}
}
return script;
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card;
import java.io.File;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
public final class CardScriptInfo {
private String text;
private final File file;
public CardScriptInfo(final String text0, final File file0) {
text = text0;
file = file0;
}
public String getText() {
return text;
}
public File getFile() {
return file;
}
public boolean canEdit() {
return file != null;
}
public boolean trySetText(final String text0) {
if (file == null) { return false; }
try {
final PrintWriter p = new PrintWriter(file);
p.print(text0);
p.close();
text = text0;
return true;
}
catch (final Exception ex) {
System.err.println("Problem writing file - " + file);
ex.printStackTrace();
return false;
}
}
private static Map<String, CardScriptInfo> allScripts = new ConcurrentHashMap<>();
public static CardScriptInfo getScriptFor(final String name) {
CardScriptInfo script = allScripts.get(name);
if (script == null) { //attempt to load script if not previously loaded
final String filename = name.toLowerCase().replace(' ', '_').replace('-', '_').replace("'", "").replace(",", "") + ".txt";
final File file = new File(ForgeConstants.CARD_DATA_DIR + filename.charAt(0) + File.separator + filename);
if (file.exists()) {
script = new CardScriptInfo(FileUtil.readFileToString(file), file);
allScripts.put(name, script);
}
}
return script;
}
}

View File

@@ -1,9 +1,9 @@
package forge.control;
/** How 'loudly' the message should sound */
public enum ChatArea {
Room,
Match,
Whisper, // that is private
Server
}
package forge.control;
/** How 'loudly' the message should sound */
public enum ChatArea {
Room,
Match,
Whisper, // that is private
Server
}

View File

@@ -1,380 +1,380 @@
package forge.control;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe;
import forge.GuiBase;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardView;
import forge.game.event.*;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.zone.PlayerZone;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.interfaces.IGuiGame;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.player.PlayerZoneUpdate;
import forge.player.PlayerZoneUpdates;
import forge.properties.ForgePreferences.FPref;
import forge.util.Lang;
import forge.util.maps.MapOfLists;
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
private final PlayerControllerHuman humanController;
private final IGuiGame matchController;
private final Set<CardView> cardsUpdate = new HashSet<CardView>();
private final Set<CardView> cardsRefreshDetails = new HashSet<CardView>();
private final Set<PlayerView> livesUpdate = new HashSet<PlayerView>();
private final Set<PlayerView> manaPoolUpdate = new HashSet<PlayerView>();
private final PlayerZoneUpdates zonesUpdate = new PlayerZoneUpdates();
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate;
private boolean gameOver, gameFinished;
private PlayerView turnUpdate;
public FControlGameEventHandler(final PlayerControllerHuman humanController0) {
humanController = humanController0;
matchController = humanController.getGui();
}
private final Runnable processEvents = new Runnable() {
@Override
public void run() {
processEventsQueued = false;
synchronized (cardsUpdate) {
if (!cardsUpdate.isEmpty()) {
matchController.updateCards(cardsUpdate);
cardsUpdate.clear();
}
}
synchronized (cardsRefreshDetails) {
if (!cardsRefreshDetails.isEmpty()) {
matchController.refreshCardDetails(cardsRefreshDetails);
cardsRefreshDetails.clear();
}
}
synchronized (livesUpdate) {
if (!livesUpdate.isEmpty()) {
matchController.updateLives(livesUpdate);
livesUpdate.clear();
}
}
synchronized (manaPoolUpdate) {
if (!manaPoolUpdate.isEmpty()) {
matchController.updateManaPool(manaPoolUpdate);
manaPoolUpdate.clear();
}
}
if (turnUpdate != null) {
matchController.updateTurn(turnUpdate);
turnUpdate = null;
}
if (needPhaseUpdate) {
needPhaseUpdate = false;
matchController.updatePhase();
}
if (needCombatUpdate) {
needCombatUpdate = false;
matchController.showCombat();
}
if (needStackUpdate) {
needStackUpdate = false;
matchController.updateStack();
}
if (needPlayerControlUpdate) {
needPlayerControlUpdate = false;
matchController.updatePlayerControl();
}
synchronized (zonesUpdate) {
if (!zonesUpdate.isEmpty()) {
// Copy to prevent concurrency issues
matchController.updateZones(new PlayerZoneUpdates(zonesUpdate));
zonesUpdate.clear();
}
}
if (gameOver) {
gameOver = false;
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
}
if (gameFinished) {
gameFinished = false;
final PlayerView localPlayer = humanController.getLocalPlayerView();
humanController.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
matchController.showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
matchController.updateButtons(localPlayer, "", "", false, false, false);
matchController.finishGame();
humanController.updateAchievements();
}
}
};
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
ev.visit(this);
}
private Void processEvent() {
if (processEventsQueued) { return null; } //avoid queuing event processing multiple times
processEventsQueued = true;
GuiBase.getInterface().invokeInEdtLater(processEvents);
return null;
}
private Void processCard(final Card card, final Set<CardView> list) {
synchronized (list) {
list.add(card.getView());
}
return processEvent();
}
private Void processCards(final Collection<Card> cards, final Set<CardView> list) {
if (cards.isEmpty()) { return null; }
synchronized (list) {
for (final Card c : cards) {
list.add(c.getView());
}
}
return processEvent();
}
private Void processPlayer(final Player player, final Set<PlayerView> list) {
synchronized (list) {
list.add(player.getView());
}
return processEvent();
}
private Void updateZone(final Zone z) {
if (z == null) { return null; }
return updateZone(z.getPlayer(), z.getZoneType());
}
private Void updateZone(final Player p, final ZoneType z) {
if (p == null || z == null) { return null; }
synchronized (zonesUpdate) {
zonesUpdate.add(new PlayerZoneUpdate(PlayerView.get(p), z));
}
return processEvent();
}
@Override
public Void visit(final GameEventTurnPhase ev) {
needPhaseUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventPlayerPriority event) {
needCombatUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventTurnBegan event) {
turnUpdate = event.turnOwner.getView();
processPlayer(event.turnOwner, livesUpdate);
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
// anything except stack will get here
updateZone(event.turnOwner, ZoneType.Battlefield);
}
return processEvent();
}
@Override
public Void visit(final GameEventAnteCardsSelected ev) {
final List<CardView> options = Lists.newArrayList();
for (final Entry<Player, Card> kv : ev.cards.entries()) {
//use fake card so real cards appear with proper formatting
final CardView fakeCard = new CardView(-1, null, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
options.add(fakeCard);
options.add(kv.getValue().getView());
}
humanController.getGui().reveal("These cards were chosen to ante", options);
return null;
}
@Override
public Void visit(final GameEventPlayerControl ev) {
if (ev.player.getGame().isGameOver()) {
return null;
}
final PlayerControllerHuman newController;
if (ev.newController instanceof PlayerControllerHuman) {
newController = (PlayerControllerHuman) ev.newController;
} else {
newController = null;
}
matchController.setGameController(PlayerView.get(ev.player), newController);
needPlayerControlUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventGameOutcome ev) {
gameOver = true;
return processEvent();
}
@Override
public Void visit(final GameEventGameFinished ev) {
gameFinished = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellAbilityCast event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellResolved event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellRemovedFromStack event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventZone event) {
if (event.player != null) {
// anything except stack will get here
updateZone(event.player, event.zoneType);
return processEvent();
}
return null;
}
@Override
public Void visit(final GameEventCardAttachment event) {
final Game game = event.equipment.getGame();
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
if (event.oldEntiy instanceof Card) {
updateZone(game.getZoneOf((Card)event.oldEntiy));
}
if (event.newTarget instanceof Card) {
updateZone(game.getZoneOf((Card)event.newTarget));
}
updateZone(zEq);
return processEvent();
}
@Override
public Void visit(final GameEventCardTapped event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardPhased event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardDamaged event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardCounters event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventBlockersDeclared event) {
final Set<Card> cards = new HashSet<Card>();
for (final MapOfLists<Card, Card> kv : event.blockers.values()) {
for (final Collection<Card> blockers : kv.values()) {
cards.addAll(blockers);
}
}
return processCards(cards, cardsUpdate);
}
@Override
public Void visit(final GameEventAttackersDeclared event) {
return processCards(event.attackersMap.values(), cardsUpdate);
}
@Override
public Void visit(final GameEventCombatChanged event) {
needCombatUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventCombatEnded event) {
needCombatUpdate = true;
// This should remove sword/shield icons from combatants by the time game moves to M2
processCards(event.attackers, cardsUpdate);
return processCards(event.blockers, cardsUpdate);
}
@Override
public Void visit(final GameEventCardChangeZone event) {
updateZone(event.from);
return updateZone(event.to);
}
@Override
public Void visit(final GameEventCardStatsChanged event) {
processCards(event.cards, cardsRefreshDetails);
return processCards(event.cards, cardsUpdate);
}
@Override
public Void visit(final GameEventPlayerStatsChanged event) {
final CardCollection cards = new CardCollection();
for (final Player p : event.players) {
cards.addAll(p.getAllCards());
processPlayer(p, livesUpdate);
}
return processCards(cards, cardsRefreshDetails);
}
@Override
public Void visit(final GameEventShuffle event) {
return updateZone(event.player.getZone(ZoneType.Library));
}
@Override
public Void visit(final GameEventManaPool event) {
return processPlayer(event.player, manaPoolUpdate);
}
@Override
public Void visit(final GameEventPlayerLivesChanged event) {
return processPlayer(event.player, livesUpdate);
}
@Override
public Void visit(final GameEventPlayerPoisoned event) {
return processPlayer(event.receiver, livesUpdate);
}
@Override
public Void visit(final GameEventPlayerCounters event) {
return processPlayer(event.receiver, livesUpdate);
}
package forge.control;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe;
import forge.GuiBase;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardView;
import forge.game.event.*;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.zone.PlayerZone;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.interfaces.IGuiGame;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.player.PlayerZoneUpdate;
import forge.player.PlayerZoneUpdates;
import forge.properties.ForgePreferences.FPref;
import forge.util.Lang;
import forge.util.maps.MapOfLists;
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
private final PlayerControllerHuman humanController;
private final IGuiGame matchController;
private final Set<CardView> cardsUpdate = new HashSet<CardView>();
private final Set<CardView> cardsRefreshDetails = new HashSet<CardView>();
private final Set<PlayerView> livesUpdate = new HashSet<PlayerView>();
private final Set<PlayerView> manaPoolUpdate = new HashSet<PlayerView>();
private final PlayerZoneUpdates zonesUpdate = new PlayerZoneUpdates();
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate;
private boolean gameOver, gameFinished;
private PlayerView turnUpdate;
public FControlGameEventHandler(final PlayerControllerHuman humanController0) {
humanController = humanController0;
matchController = humanController.getGui();
}
private final Runnable processEvents = new Runnable() {
@Override
public void run() {
processEventsQueued = false;
synchronized (cardsUpdate) {
if (!cardsUpdate.isEmpty()) {
matchController.updateCards(cardsUpdate);
cardsUpdate.clear();
}
}
synchronized (cardsRefreshDetails) {
if (!cardsRefreshDetails.isEmpty()) {
matchController.refreshCardDetails(cardsRefreshDetails);
cardsRefreshDetails.clear();
}
}
synchronized (livesUpdate) {
if (!livesUpdate.isEmpty()) {
matchController.updateLives(livesUpdate);
livesUpdate.clear();
}
}
synchronized (manaPoolUpdate) {
if (!manaPoolUpdate.isEmpty()) {
matchController.updateManaPool(manaPoolUpdate);
manaPoolUpdate.clear();
}
}
if (turnUpdate != null) {
matchController.updateTurn(turnUpdate);
turnUpdate = null;
}
if (needPhaseUpdate) {
needPhaseUpdate = false;
matchController.updatePhase();
}
if (needCombatUpdate) {
needCombatUpdate = false;
matchController.showCombat();
}
if (needStackUpdate) {
needStackUpdate = false;
matchController.updateStack();
}
if (needPlayerControlUpdate) {
needPlayerControlUpdate = false;
matchController.updatePlayerControl();
}
synchronized (zonesUpdate) {
if (!zonesUpdate.isEmpty()) {
// Copy to prevent concurrency issues
matchController.updateZones(new PlayerZoneUpdates(zonesUpdate));
zonesUpdate.clear();
}
}
if (gameOver) {
gameOver = false;
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
}
if (gameFinished) {
gameFinished = false;
final PlayerView localPlayer = humanController.getLocalPlayerView();
humanController.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
matchController.showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
matchController.updateButtons(localPlayer, "", "", false, false, false);
matchController.finishGame();
humanController.updateAchievements();
}
}
};
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
ev.visit(this);
}
private Void processEvent() {
if (processEventsQueued) { return null; } //avoid queuing event processing multiple times
processEventsQueued = true;
GuiBase.getInterface().invokeInEdtLater(processEvents);
return null;
}
private Void processCard(final Card card, final Set<CardView> list) {
synchronized (list) {
list.add(card.getView());
}
return processEvent();
}
private Void processCards(final Collection<Card> cards, final Set<CardView> list) {
if (cards.isEmpty()) { return null; }
synchronized (list) {
for (final Card c : cards) {
list.add(c.getView());
}
}
return processEvent();
}
private Void processPlayer(final Player player, final Set<PlayerView> list) {
synchronized (list) {
list.add(player.getView());
}
return processEvent();
}
private Void updateZone(final Zone z) {
if (z == null) { return null; }
return updateZone(z.getPlayer(), z.getZoneType());
}
private Void updateZone(final Player p, final ZoneType z) {
if (p == null || z == null) { return null; }
synchronized (zonesUpdate) {
zonesUpdate.add(new PlayerZoneUpdate(PlayerView.get(p), z));
}
return processEvent();
}
@Override
public Void visit(final GameEventTurnPhase ev) {
needPhaseUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventPlayerPriority event) {
needCombatUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventTurnBegan event) {
turnUpdate = event.turnOwner.getView();
processPlayer(event.turnOwner, livesUpdate);
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
// anything except stack will get here
updateZone(event.turnOwner, ZoneType.Battlefield);
}
return processEvent();
}
@Override
public Void visit(final GameEventAnteCardsSelected ev) {
final List<CardView> options = Lists.newArrayList();
for (final Entry<Player, Card> kv : ev.cards.entries()) {
//use fake card so real cards appear with proper formatting
final CardView fakeCard = new CardView(-1, null, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
options.add(fakeCard);
options.add(kv.getValue().getView());
}
humanController.getGui().reveal("These cards were chosen to ante", options);
return null;
}
@Override
public Void visit(final GameEventPlayerControl ev) {
if (ev.player.getGame().isGameOver()) {
return null;
}
final PlayerControllerHuman newController;
if (ev.newController instanceof PlayerControllerHuman) {
newController = (PlayerControllerHuman) ev.newController;
} else {
newController = null;
}
matchController.setGameController(PlayerView.get(ev.player), newController);
needPlayerControlUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventGameOutcome ev) {
gameOver = true;
return processEvent();
}
@Override
public Void visit(final GameEventGameFinished ev) {
gameFinished = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellAbilityCast event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellResolved event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventSpellRemovedFromStack event) {
needStackUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventZone event) {
if (event.player != null) {
// anything except stack will get here
updateZone(event.player, event.zoneType);
return processEvent();
}
return null;
}
@Override
public Void visit(final GameEventCardAttachment event) {
final Game game = event.equipment.getGame();
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
if (event.oldEntiy instanceof Card) {
updateZone(game.getZoneOf((Card)event.oldEntiy));
}
if (event.newTarget instanceof Card) {
updateZone(game.getZoneOf((Card)event.newTarget));
}
updateZone(zEq);
return processEvent();
}
@Override
public Void visit(final GameEventCardTapped event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardPhased event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardDamaged event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventCardCounters event) {
processCard(event.card, cardsUpdate);
return processEvent();
}
@Override
public Void visit(final GameEventBlockersDeclared event) {
final Set<Card> cards = new HashSet<Card>();
for (final MapOfLists<Card, Card> kv : event.blockers.values()) {
for (final Collection<Card> blockers : kv.values()) {
cards.addAll(blockers);
}
}
return processCards(cards, cardsUpdate);
}
@Override
public Void visit(final GameEventAttackersDeclared event) {
return processCards(event.attackersMap.values(), cardsUpdate);
}
@Override
public Void visit(final GameEventCombatChanged event) {
needCombatUpdate = true;
return processEvent();
}
@Override
public Void visit(final GameEventCombatEnded event) {
needCombatUpdate = true;
// This should remove sword/shield icons from combatants by the time game moves to M2
processCards(event.attackers, cardsUpdate);
return processCards(event.blockers, cardsUpdate);
}
@Override
public Void visit(final GameEventCardChangeZone event) {
updateZone(event.from);
return updateZone(event.to);
}
@Override
public Void visit(final GameEventCardStatsChanged event) {
processCards(event.cards, cardsRefreshDetails);
return processCards(event.cards, cardsUpdate);
}
@Override
public Void visit(final GameEventPlayerStatsChanged event) {
final CardCollection cards = new CardCollection();
for (final Player p : event.players) {
cards.addAll(p.getAllCards());
processPlayer(p, livesUpdate);
}
return processCards(cards, cardsRefreshDetails);
}
@Override
public Void visit(final GameEventShuffle event) {
return updateZone(event.player.getZone(ZoneType.Library));
}
@Override
public Void visit(final GameEventManaPool event) {
return processPlayer(event.player, manaPoolUpdate);
}
@Override
public Void visit(final GameEventPlayerLivesChanged event) {
return processPlayer(event.player, livesUpdate);
}
@Override
public Void visit(final GameEventPlayerPoisoned event) {
return processPlayer(event.receiver, livesUpdate);
}
@Override
public Void visit(final GameEventPlayerCounters event) {
return processPlayer(event.receiver, livesUpdate);
}
}

View File

@@ -1,221 +1,221 @@
package forge.control;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.eventbus.Subscribe;
import forge.FThreads;
import forge.game.Game;
import forge.game.card.CardView;
import forge.game.event.GameEvent;
import forge.game.event.GameEventBlockersDeclared;
import forge.game.event.GameEventGameFinished;
import forge.game.event.GameEventGameStarted;
import forge.game.event.GameEventLandPlayed;
import forge.game.event.GameEventPlayerPriority;
import forge.game.event.GameEventSpellAbilityCast;
import forge.game.event.GameEventSpellResolved;
import forge.game.event.GameEventTurnPhase;
import forge.game.event.IGameEventVisitor;
import forge.match.input.InputPlaybackControl;
import forge.player.PlayerControllerHuman;
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
private InputPlaybackControl inputPlayback;
private final AtomicBoolean paused = new AtomicBoolean(false);
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
private final PlayerControllerHuman humanController;
public FControlGamePlayback(final PlayerControllerHuman humanController0) {
this.humanController = humanController0;
}
public final PlayerControllerHuman getController() {
return humanController;
}
public InputPlaybackControl getInput() {
return inputPlayback;
}
private Game game;
public Game getGame() {
return game;
}
public void setGame(final Game game0) {
game = game0;
inputPlayback = new InputPlaybackControl(game, this);
}
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
ev.visit(this);
}
public static final int phasesDelay = 200;
public static final int combatDelay = 400;
public static final int castDelay = 400;
public static final int resolveDelay = 400;
private boolean fasterPlayback = false;
private void pauseForEvent(final int delay) {
try {
Thread.sleep(fasterPlayback ? delay / 10 : delay);
} catch (final InterruptedException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
@Override
public Void visit(final GameEventBlockersDeclared event) {
pauseForEvent(combatDelay);
return super.visit(event);
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase)
*/
@Override
public Void visit(final GameEventTurnPhase ev) {
try {
final boolean isUiToStop = !humanController.getGui().isUiSetToSkipPhase(ev.playerTurn.getView(), ev.phase);
switch(ev.phase) {
case COMBAT_END:
case COMBAT_DECLARE_ATTACKERS:
case COMBAT_DECLARE_BLOCKERS:
if (getGame().getPhaseHandler().inCombat()) {
pauseForEvent(combatDelay);
}
break;
default:
if (isUiToStop) {
pauseForEvent(phasesDelay);
}
break;
}
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished)
*/
@Override
public Void visit(final GameEventGameFinished event) {
humanController.getInputQueue().removeInput(inputPlayback);
return null;
}
@Override
public Void visit(final GameEventGameStarted event) {
humanController.getInputQueue().setInput(inputPlayback);
return null;
}
@Override
public Void visit(final GameEventLandPlayed event) {
pauseForEvent(resolveDelay);
return super.visit(event);
}
@Override
public Void visit(final GameEventSpellResolved event) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
humanController.getGui().setCard(CardView.get(event.spell.getHostCard()));
}
});
pauseForEvent(resolveDelay);
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast)
*/
@Override
public Void visit(final GameEventSpellAbilityCast event) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
humanController.getGui().setCard(CardView.get(event.sa.getHostCard()));
}
});
pauseForEvent(castDelay);
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
*/
@Override
public Void visit(final GameEventPlayerPriority event) {
inputPlayback.updateTurnMessage();
if (paused.get()) {
try {
gameThreadPauser.await();
gameThreadPauser.reset();
}
catch (final InterruptedException e) {
e.printStackTrace();
}
catch (final BrokenBarrierException e) {
e.printStackTrace();
}
}
return null;
}
public void onGameStopRequested() {
paused.set(false);
if (gameThreadPauser.getNumberWaiting() != 0) {
releaseGameThread();
}
}
private void releaseGameThread() {
// just need to run another thread through the barrier... not edt preferrably :)
getGame().getAction().invoke(new Runnable() {
@Override
public void run() {
try {
gameThreadPauser.await();
} catch (final InterruptedException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
} catch (final BrokenBarrierException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
});
}
public void resume() {
paused.set(false);
releaseGameThread();
}
public void pause() {
paused.set(true);
}
public void singleStep() {
releaseGameThread();
}
public void setSpeed(final boolean isFast) {
fasterPlayback = isFast;
}
package forge.control;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.eventbus.Subscribe;
import forge.FThreads;
import forge.game.Game;
import forge.game.card.CardView;
import forge.game.event.GameEvent;
import forge.game.event.GameEventBlockersDeclared;
import forge.game.event.GameEventGameFinished;
import forge.game.event.GameEventGameStarted;
import forge.game.event.GameEventLandPlayed;
import forge.game.event.GameEventPlayerPriority;
import forge.game.event.GameEventSpellAbilityCast;
import forge.game.event.GameEventSpellResolved;
import forge.game.event.GameEventTurnPhase;
import forge.game.event.IGameEventVisitor;
import forge.match.input.InputPlaybackControl;
import forge.player.PlayerControllerHuman;
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
private InputPlaybackControl inputPlayback;
private final AtomicBoolean paused = new AtomicBoolean(false);
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
private final PlayerControllerHuman humanController;
public FControlGamePlayback(final PlayerControllerHuman humanController0) {
this.humanController = humanController0;
}
public final PlayerControllerHuman getController() {
return humanController;
}
public InputPlaybackControl getInput() {
return inputPlayback;
}
private Game game;
public Game getGame() {
return game;
}
public void setGame(final Game game0) {
game = game0;
inputPlayback = new InputPlaybackControl(game, this);
}
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
ev.visit(this);
}
public static final int phasesDelay = 200;
public static final int combatDelay = 400;
public static final int castDelay = 400;
public static final int resolveDelay = 400;
private boolean fasterPlayback = false;
private void pauseForEvent(final int delay) {
try {
Thread.sleep(fasterPlayback ? delay / 10 : delay);
} catch (final InterruptedException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
@Override
public Void visit(final GameEventBlockersDeclared event) {
pauseForEvent(combatDelay);
return super.visit(event);
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase)
*/
@Override
public Void visit(final GameEventTurnPhase ev) {
try {
final boolean isUiToStop = !humanController.getGui().isUiSetToSkipPhase(ev.playerTurn.getView(), ev.phase);
switch(ev.phase) {
case COMBAT_END:
case COMBAT_DECLARE_ATTACKERS:
case COMBAT_DECLARE_BLOCKERS:
if (getGame().getPhaseHandler().inCombat()) {
pauseForEvent(combatDelay);
}
break;
default:
if (isUiToStop) {
pauseForEvent(phasesDelay);
}
break;
}
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished)
*/
@Override
public Void visit(final GameEventGameFinished event) {
humanController.getInputQueue().removeInput(inputPlayback);
return null;
}
@Override
public Void visit(final GameEventGameStarted event) {
humanController.getInputQueue().setInput(inputPlayback);
return null;
}
@Override
public Void visit(final GameEventLandPlayed event) {
pauseForEvent(resolveDelay);
return super.visit(event);
}
@Override
public Void visit(final GameEventSpellResolved event) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
humanController.getGui().setCard(CardView.get(event.spell.getHostCard()));
}
});
pauseForEvent(resolveDelay);
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast)
*/
@Override
public Void visit(final GameEventSpellAbilityCast event) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
humanController.getGui().setCard(CardView.get(event.sa.getHostCard()));
}
});
pauseForEvent(castDelay);
return null;
}
/* (non-Javadoc)
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
*/
@Override
public Void visit(final GameEventPlayerPriority event) {
inputPlayback.updateTurnMessage();
if (paused.get()) {
try {
gameThreadPauser.await();
gameThreadPauser.reset();
}
catch (final InterruptedException e) {
e.printStackTrace();
}
catch (final BrokenBarrierException e) {
e.printStackTrace();
}
}
return null;
}
public void onGameStopRequested() {
paused.set(false);
if (gameThreadPauser.getNumberWaiting() != 0) {
releaseGameThread();
}
}
private void releaseGameThread() {
// just need to run another thread through the barrier... not edt preferrably :)
getGame().getAction().invoke(new Runnable() {
@Override
public void run() {
try {
gameThreadPauser.await();
} catch (final InterruptedException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
} catch (final BrokenBarrierException e) {
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
});
}
public void resume() {
paused.set(false);
releaseGameThread();
}
public void pause() {
paused.set(true);
}
public void singleStep() {
releaseGameThread();
}
public void setSpeed(final boolean isFast) {
fasterPlayback = isFast;
}
}

View File

@@ -1,3 +1,3 @@
/** Controller (as in model-view-controller) for Forge. */
package forge.control;
/** Controller (as in model-view-controller) for Forge. */
package forge.control;

View File

@@ -1,144 +1,144 @@
package forge.deck;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.CardRulesPredicates;
import forge.deck.io.CardThemedMatrixIO;
import forge.deck.io.DeckStorage;
import forge.game.GameFormat;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.storage.IStorage;
import forge.util.storage.StorageImmediatelySerialized;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
import java.util.*;
/**
* Created by maustin on 09/05/2017.
*/
public final class CardRelationMatrixGenerator {
public static HashMap<GameFormat,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
public static void initialize(){
HashMap<String,List<Map.Entry<PaperCard,Integer>>> standardMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getStandard());
HashMap<String,List<Map.Entry<PaperCard,Integer>>> modernMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getModern());
if(standardMap==null || modernMap==null){
reInitialize();
return;
}
cardPools.put(FModel.getFormats().getStandard(),standardMap);
cardPools.put(FModel.getFormats().getModern(),modernMap);
}
public static void reInitialize(){
cardPools.put(FModel.getFormats().getStandard(),initializeFormat(FModel.getFormats().getStandard()));
cardPools.put(FModel.getFormats().getModern(),initializeFormat(FModel.getFormats().getModern()));
for(GameFormat format:cardPools.keySet()){
HashMap<String,List<Map.Entry<PaperCard,Integer>>> map = cardPools.get(format);
CardThemedMatrixIO.saveMatrix(format,map);
}
}
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> initializeFormat(GameFormat format){
IStorage<Deck> decks = new StorageImmediatelySerialized<Deck>("Generator", new DeckStorage(new File(ForgeConstants.DECK_GEN_DIR+ForgeConstants.PATH_SEPARATOR+format.getName()),
ForgeConstants.DECK_GEN_DIR, false),
true);
final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards()
, Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES));
List<PaperCard> cardList = Lists.newArrayList(cards);
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
Map<String, Integer> cardIntegerMap = new HashMap<>();
Map<Integer, PaperCard> integerCardMap = new HashMap<>();
for (int i=0; i<cardList.size(); ++i){
cardIntegerMap.put(cardList.get(i).getName(),i);
integerCardMap.put(i,cardList.get(i));
}
int[][] matrix = new int[cardList.size()][cardList.size()];
for (PaperCard card:cardList){
for (Deck deck:decks){
if (deck.getMain().contains(card)){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES))){
if (!pairCard.getName().equals(card.getName())){
try {
int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1;
}catch (NullPointerException ne){
//Todo: Not sure what was failing here
}
}
}
}
}
}
HashMap<String,List<Map.Entry<PaperCard,Integer>>> cardPools = new HashMap<>();
for (PaperCard card:cardList){
int col=cardIntegerMap.get(card.getName());
int[] distances = matrix[col];
int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances)));
if (max>0) {
ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
Integer[] indices = comparator.createIndexArray();
Arrays.sort(indices, comparator);
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
int k=0;
boolean excludeThisCard=false;//if there are too few cards with at least one connection
for (int j=0;j<20;++k){
if(distances[indices[cardList.size()-1-k]]==0){
excludeThisCard = true;
break;
}
PaperCard cardToAdd=integerCardMap.get(indices[cardList.size()-1-k]);
if(!cardToAdd.getRules().getMainPart().getType().isLand()){//need x non-land cards
++j;
}
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(cardToAdd,distances[indices[cardList.size()-1-k]]));
};
if(excludeThisCard){
continue;
}
cardPools.put(card.getName(),deckPool);
}
}
return cardPools;
}
public static class ArrayIndexComparator implements Comparator<Integer>
{
private final Integer[] array;
public ArrayIndexComparator(Integer[] array)
{
this.array = array;
}
public Integer[] createIndexArray()
{
Integer[] indexes = new Integer[array.length];
for (int i = 0; i < array.length; i++)
{
indexes[i] = i; // Autoboxing
}
return indexes;
}
@Override
public int compare(Integer index1, Integer index2)
{
// Autounbox from Integer to int to use as array indexes
return array[index1].compareTo(array[index2]);
}
}
}
package forge.deck;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.CardRulesPredicates;
import forge.deck.io.CardThemedMatrixIO;
import forge.deck.io.DeckStorage;
import forge.game.GameFormat;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.storage.IStorage;
import forge.util.storage.StorageImmediatelySerialized;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
import java.util.*;
/**
* Created by maustin on 09/05/2017.
*/
public final class CardRelationMatrixGenerator {
public static HashMap<GameFormat,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
public static void initialize(){
HashMap<String,List<Map.Entry<PaperCard,Integer>>> standardMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getStandard());
HashMap<String,List<Map.Entry<PaperCard,Integer>>> modernMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getModern());
if(standardMap==null || modernMap==null){
reInitialize();
return;
}
cardPools.put(FModel.getFormats().getStandard(),standardMap);
cardPools.put(FModel.getFormats().getModern(),modernMap);
}
public static void reInitialize(){
cardPools.put(FModel.getFormats().getStandard(),initializeFormat(FModel.getFormats().getStandard()));
cardPools.put(FModel.getFormats().getModern(),initializeFormat(FModel.getFormats().getModern()));
for(GameFormat format:cardPools.keySet()){
HashMap<String,List<Map.Entry<PaperCard,Integer>>> map = cardPools.get(format);
CardThemedMatrixIO.saveMatrix(format,map);
}
}
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> initializeFormat(GameFormat format){
IStorage<Deck> decks = new StorageImmediatelySerialized<Deck>("Generator", new DeckStorage(new File(ForgeConstants.DECK_GEN_DIR+ForgeConstants.PATH_SEPARATOR+format.getName()),
ForgeConstants.DECK_GEN_DIR, false),
true);
final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards()
, Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES));
List<PaperCard> cardList = Lists.newArrayList(cards);
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
Map<String, Integer> cardIntegerMap = new HashMap<>();
Map<Integer, PaperCard> integerCardMap = new HashMap<>();
for (int i=0; i<cardList.size(); ++i){
cardIntegerMap.put(cardList.get(i).getName(),i);
integerCardMap.put(i,cardList.get(i));
}
int[][] matrix = new int[cardList.size()][cardList.size()];
for (PaperCard card:cardList){
for (Deck deck:decks){
if (deck.getMain().contains(card)){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES))){
if (!pairCard.getName().equals(card.getName())){
try {
int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1;
}catch (NullPointerException ne){
//Todo: Not sure what was failing here
}
}
}
}
}
}
HashMap<String,List<Map.Entry<PaperCard,Integer>>> cardPools = new HashMap<>();
for (PaperCard card:cardList){
int col=cardIntegerMap.get(card.getName());
int[] distances = matrix[col];
int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances)));
if (max>0) {
ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
Integer[] indices = comparator.createIndexArray();
Arrays.sort(indices, comparator);
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
int k=0;
boolean excludeThisCard=false;//if there are too few cards with at least one connection
for (int j=0;j<20;++k){
if(distances[indices[cardList.size()-1-k]]==0){
excludeThisCard = true;
break;
}
PaperCard cardToAdd=integerCardMap.get(indices[cardList.size()-1-k]);
if(!cardToAdd.getRules().getMainPart().getType().isLand()){//need x non-land cards
++j;
}
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(cardToAdd,distances[indices[cardList.size()-1-k]]));
};
if(excludeThisCard){
continue;
}
cardPools.put(card.getName(),deckPool);
}
}
return cardPools;
}
public static class ArrayIndexComparator implements Comparator<Integer>
{
private final Integer[] array;
public ArrayIndexComparator(Integer[] array)
{
this.array = array;
}
public Integer[] createIndexArray()
{
Integer[] indexes = new Integer[array.length];
for (int i = 0; i < array.length; i++)
{
indexes[i] = i; // Autoboxing
}
return indexes;
}
@Override
public int compare(Integer index1, Integer index2)
{
// Autounbox from Integer to int to use as array indexes
return array[index1].compareTo(array[index2]);
}
}
}

View File

@@ -1,64 +1,64 @@
package forge.deck;
import forge.card.CardEdition;
import forge.game.GameFormat;
import java.util.ArrayList;
import java.util.List;
/**
* Created by maustin on 09/05/2017.
*/
public class CardThemedDeckGenerator extends DeckProxy implements Comparable<CardThemedDeckGenerator> {
public static List<DeckProxy> getMatrixDecks(GameFormat format, boolean isForAi){
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
for(String card: CardRelationMatrixGenerator.cardPools.get(format).keySet()) {
decks.add(new CardThemedDeckGenerator(card, format, isForAi));
}
return decks;
}
private final String name;
private final int index;
private final GameFormat format;
private final boolean isForAi;
private CardThemedDeckGenerator(String cardName, GameFormat format0, boolean isForAi0) {
super();
name = cardName;
index = 0;
format=format0;
isForAi=isForAi0;
}
public CardEdition getEdition() {
return CardEdition.UNKNOWN;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final CardThemedDeckGenerator d) {
return name.compareTo(d.getName());
}
@Override
public Deck getDeck() {
return DeckgenUtil.buildCardGenDeck(name,format,isForAi);
}
@Override
public boolean isGeneratedDeck() {
return true;
}
}
package forge.deck;
import forge.card.CardEdition;
import forge.game.GameFormat;
import java.util.ArrayList;
import java.util.List;
/**
* Created by maustin on 09/05/2017.
*/
public class CardThemedDeckGenerator extends DeckProxy implements Comparable<CardThemedDeckGenerator> {
public static List<DeckProxy> getMatrixDecks(GameFormat format, boolean isForAi){
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
for(String card: CardRelationMatrixGenerator.cardPools.get(format).keySet()) {
decks.add(new CardThemedDeckGenerator(card, format, isForAi));
}
return decks;
}
private final String name;
private final int index;
private final GameFormat format;
private final boolean isForAi;
private CardThemedDeckGenerator(String cardName, GameFormat format0, boolean isForAi0) {
super();
name = cardName;
index = 0;
format=format0;
isForAi=isForAi0;
}
public CardEdition getEdition() {
return CardEdition.UNKNOWN;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final CardThemedDeckGenerator d) {
return name.compareTo(d.getName());
}
@Override
public Deck getDeck() {
return DeckgenUtil.buildCardGenDeck(name,format,isForAi);
}
@Override
public boolean isGeneratedDeck() {
return true;
}
}

View File

@@ -1,73 +1,73 @@
package forge.deck;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import forge.card.CardEdition;
import forge.item.PaperCard;
import forge.itemmanager.IItemManager;
public class ColorDeckGenerator extends DeckProxy implements Comparable<ColorDeckGenerator> {
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
final String[] colors = new String[] { "Random 1", "Random 2", "Random 3",
"White", "Blue", "Black", "Red", "Green" };
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
for (int i = 0; i < colors.length; i++) {
decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, formatFilter0, isAi0));
}
return decks;
}
private final String name;
private final int index;
private final IItemManager<DeckProxy> lstDecks;
private final boolean isAi;
private final Predicate<PaperCard> formatFilter;
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0,final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
super();
name = name0;
index = index0;
lstDecks = lstDecks0;
isAi = isAi0;
formatFilter = formatFilter0;
}
public CardEdition getEdition() {
return CardEdition.UNKNOWN;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final ColorDeckGenerator d) {
return Integer.compare(index, d.index);
}
@Override
public Deck getDeck() {
final List<String> selection = new ArrayList<String>();
for (final DeckProxy deck : lstDecks.getSelectedItems()) {
selection.add(deck.getName());
}
if (DeckgenUtil.colorCheck(selection)) {
return DeckgenUtil.buildColorDeck(selection, formatFilter, isAi);
}
return null;
}
@Override
public boolean isGeneratedDeck() {
return true;
}
package forge.deck;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import forge.card.CardEdition;
import forge.item.PaperCard;
import forge.itemmanager.IItemManager;
public class ColorDeckGenerator extends DeckProxy implements Comparable<ColorDeckGenerator> {
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
final String[] colors = new String[] { "Random 1", "Random 2", "Random 3",
"White", "Blue", "Black", "Red", "Green" };
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
for (int i = 0; i < colors.length; i++) {
decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, formatFilter0, isAi0));
}
return decks;
}
private final String name;
private final int index;
private final IItemManager<DeckProxy> lstDecks;
private final boolean isAi;
private final Predicate<PaperCard> formatFilter;
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0,final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
super();
name = name0;
index = index0;
lstDecks = lstDecks0;
isAi = isAi0;
formatFilter = formatFilter0;
}
public CardEdition getEdition() {
return CardEdition.UNKNOWN;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final ColorDeckGenerator d) {
return Integer.compare(index, d.index);
}
@Override
public Deck getDeck() {
final List<String> selection = new ArrayList<String>();
for (final DeckProxy deck : lstDecks.getSelectedItems()) {
selection.add(deck.getName());
}
if (DeckgenUtil.colorCheck(selection)) {
return DeckgenUtil.buildColorDeck(selection, formatFilter, isAi);
}
return null;
}
@Override
public boolean isGeneratedDeck() {
return true;
}
}

View File

@@ -1,245 +1,245 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck;
import forge.deck.CardPool;
import forge.deck.generation.DeckGeneratorBase;
import forge.deck.generation.IDeckGenPool;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.MyRandom;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* <p>
* ThemeDeckGenerator class.
* </p>
*
* @author Forge
* @version $Id: ThemeDeckGenerator.java 25022 2014-03-02 14:19:50Z teferi $
*/
public class DeckGeneratorTheme extends DeckGeneratorBase {
@Override
protected final float getLandPercentage() {
return 0.44f;
}
@Override
protected final float getCreaturePercentage() {
return 0.33f;
}
@Override
protected final float getSpellPercentage() {
return 0.23f;
}
private int basicLandPercentage = 0;
private String basicLandSet = null;
private boolean testing = false;
/**
* <p>
* Constructor for ThemeDeckGenerator.
* </p>
*/
public DeckGeneratorTheme(IDeckGenPool pool0) {
super(pool0, DeckFormat.Constructed);
setBasicLandPool(null);
this.maxDuplicates = 4;
}
/**
* <p>
* getThemeNames.
* </p>
*
* @return a {@link java.util.ArrayList} object.
*/
public static final List<String> getThemeNames() {
final List<String> ltNames = new ArrayList<String>();
final File file = new File(ForgeConstants.THEMES_DIR);
if (!file.exists()) {
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- file not found -- filename is "
+ file.getAbsolutePath());
}
if (!file.isDirectory()) {
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- not a directory -- "
+ file.getAbsolutePath());
}
final String[] fileList = file.list();
for (final String element : fileList) {
if (element.endsWith(".thm")) {
ltNames.add(element.substring(0, element.indexOf(".thm")));
}
}
return ltNames;
}
/**
* <p>
* getThemeDeck.
* </p>
*
* @param themeName
* a {@link java.lang.String} object.
* @param size
* a int.
* @return a {@link forge.CardList} object.
*/
public final CardPool getThemeDeck(final String themeName, final int size, final StringBuilder errorBuilder) {
String s = "";
String[] ss;
// read theme file
final String tFileName = ForgeConstants.THEMES_DIR + "/" + themeName + ".thm";
List<String> lines = FileUtil.readFile(tFileName);
final List<Grp> groups = readGroups(lines);
// begin assigning cards to the deck
final Random r = MyRandom.getRandom();
for (int i = 0; i < groups.size(); i++) {
final Grp g = groups.get(i);
final float p = (float) (g.percentage * .01);
final int grpCnt = (int) (p * size);
final int cnSize = g.cardnames.size();
errorBuilder.append("Group" + i + ":" + grpCnt + "\n");
for (int j = 0; j < grpCnt; j++) {
s = g.cardnames.get(r.nextInt(cnSize));
ss = s.split("\\|");
int lc = 0;
while ((cardCounts.get(ss[0]) >= g.maxCnt) || (lc > 999)) {
// looping
// forever
s = g.cardnames.get(r.nextInt(cnSize));
ss = s.split("\\|");
lc++;
}
if (lc > 999) {
throw new RuntimeException("ThemeDeckGenerator : getThemeDeck -- looped too much -- filename is "
+ tFileName);
}
final int n = cardCounts.get(ss[0]);
if (ss.length == 1) {
tDeck.add(pool.getCard(ss[0]));
}
else {
tDeck.add(pool.getCard(ss[0],ss[1]));
}
cardCounts.put(ss[0], n + 1);
errorBuilder.append(s + "\n");
}
}
int numBLands;
if (basicLandPercentage > 0) { // if theme explicitly defines this
numBLands = (int) (size * basicLandPercentage / 100f);
}
else { // otherwise, just fill in the rest of the deck with basic lands
numBLands = size - tDeck.countAll();
}
errorBuilder.append("numBLands:" + numBLands + "\n");
addBasicLand(numBLands,basicLandSet);
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
adjustDeckSize(size);
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
if (!testing) {
errorBuilder.delete(0, errorBuilder.length()); //clear if not testing
}
return tDeck;
}
private class Grp {
/** The Cardnames. */
private final List<String> cardnames = new ArrayList<String>();
/** The Max cnt. */
private int maxCnt;
/** The Percentage. */
private int percentage;
}
private List<Grp> readGroups(List<String> lines) {
final List<Grp> groups = new ArrayList<Grp>();
Grp g = null;
for (String s : lines) {
if (s.equals("End")) {
break;
}
if (s.startsWith("[Group")) {
g = new Grp();
final String[] ss = s.replaceAll("[\\[\\]]", "").split(" ");
for (final String element : ss) {
if (element.startsWith("Percentage")) {
final String p = element.substring("Percentage".length() + 1);
g.percentage = Integer.parseInt(p);
}
if (element.startsWith("MaxCnt")) {
final String m = element.substring("MaxCnt".length() + 1);
g.maxCnt = Integer.parseInt(m);
}
}
groups.add(g);
continue;
}
if (s.equals("[/Group]")) {
g = null;
}
if (s.startsWith("BasicLandPercentage")) {
final String[] ss = s.split("\\|");
basicLandPercentage = Integer.parseInt(ss[0].substring("BasicLandPercentage".length() + 1));
if(ss.length > 1)
basicLandSet = ss[1];
}
else if (s.equals("Testing")) {
testing = true;
}
else if (g != null) {
g.cardnames.add(s);
final String[] ss = s.split("\\|");
cardCounts.put(ss[0], 0);
}
}
return groups;
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck;
import forge.deck.CardPool;
import forge.deck.generation.DeckGeneratorBase;
import forge.deck.generation.IDeckGenPool;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.MyRandom;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* <p>
* ThemeDeckGenerator class.
* </p>
*
* @author Forge
* @version $Id: ThemeDeckGenerator.java 25022 2014-03-02 14:19:50Z teferi $
*/
public class DeckGeneratorTheme extends DeckGeneratorBase {
@Override
protected final float getLandPercentage() {
return 0.44f;
}
@Override
protected final float getCreaturePercentage() {
return 0.33f;
}
@Override
protected final float getSpellPercentage() {
return 0.23f;
}
private int basicLandPercentage = 0;
private String basicLandSet = null;
private boolean testing = false;
/**
* <p>
* Constructor for ThemeDeckGenerator.
* </p>
*/
public DeckGeneratorTheme(IDeckGenPool pool0) {
super(pool0, DeckFormat.Constructed);
setBasicLandPool(null);
this.maxDuplicates = 4;
}
/**
* <p>
* getThemeNames.
* </p>
*
* @return a {@link java.util.ArrayList} object.
*/
public static final List<String> getThemeNames() {
final List<String> ltNames = new ArrayList<String>();
final File file = new File(ForgeConstants.THEMES_DIR);
if (!file.exists()) {
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- file not found -- filename is "
+ file.getAbsolutePath());
}
if (!file.isDirectory()) {
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- not a directory -- "
+ file.getAbsolutePath());
}
final String[] fileList = file.list();
for (final String element : fileList) {
if (element.endsWith(".thm")) {
ltNames.add(element.substring(0, element.indexOf(".thm")));
}
}
return ltNames;
}
/**
* <p>
* getThemeDeck.
* </p>
*
* @param themeName
* a {@link java.lang.String} object.
* @param size
* a int.
* @return a {@link forge.CardList} object.
*/
public final CardPool getThemeDeck(final String themeName, final int size, final StringBuilder errorBuilder) {
String s = "";
String[] ss;
// read theme file
final String tFileName = ForgeConstants.THEMES_DIR + "/" + themeName + ".thm";
List<String> lines = FileUtil.readFile(tFileName);
final List<Grp> groups = readGroups(lines);
// begin assigning cards to the deck
final Random r = MyRandom.getRandom();
for (int i = 0; i < groups.size(); i++) {
final Grp g = groups.get(i);
final float p = (float) (g.percentage * .01);
final int grpCnt = (int) (p * size);
final int cnSize = g.cardnames.size();
errorBuilder.append("Group" + i + ":" + grpCnt + "\n");
for (int j = 0; j < grpCnt; j++) {
s = g.cardnames.get(r.nextInt(cnSize));
ss = s.split("\\|");
int lc = 0;
while ((cardCounts.get(ss[0]) >= g.maxCnt) || (lc > 999)) {
// looping
// forever
s = g.cardnames.get(r.nextInt(cnSize));
ss = s.split("\\|");
lc++;
}
if (lc > 999) {
throw new RuntimeException("ThemeDeckGenerator : getThemeDeck -- looped too much -- filename is "
+ tFileName);
}
final int n = cardCounts.get(ss[0]);
if (ss.length == 1) {
tDeck.add(pool.getCard(ss[0]));
}
else {
tDeck.add(pool.getCard(ss[0],ss[1]));
}
cardCounts.put(ss[0], n + 1);
errorBuilder.append(s + "\n");
}
}
int numBLands;
if (basicLandPercentage > 0) { // if theme explicitly defines this
numBLands = (int) (size * basicLandPercentage / 100f);
}
else { // otherwise, just fill in the rest of the deck with basic lands
numBLands = size - tDeck.countAll();
}
errorBuilder.append("numBLands:" + numBLands + "\n");
addBasicLand(numBLands,basicLandSet);
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
adjustDeckSize(size);
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
if (!testing) {
errorBuilder.delete(0, errorBuilder.length()); //clear if not testing
}
return tDeck;
}
private class Grp {
/** The Cardnames. */
private final List<String> cardnames = new ArrayList<String>();
/** The Max cnt. */
private int maxCnt;
/** The Percentage. */
private int percentage;
}
private List<Grp> readGroups(List<String> lines) {
final List<Grp> groups = new ArrayList<Grp>();
Grp g = null;
for (String s : lines) {
if (s.equals("End")) {
break;
}
if (s.startsWith("[Group")) {
g = new Grp();
final String[] ss = s.replaceAll("[\\[\\]]", "").split(" ");
for (final String element : ss) {
if (element.startsWith("Percentage")) {
final String p = element.substring("Percentage".length() + 1);
g.percentage = Integer.parseInt(p);
}
if (element.startsWith("MaxCnt")) {
final String m = element.substring("MaxCnt".length() + 1);
g.maxCnt = Integer.parseInt(m);
}
}
groups.add(g);
continue;
}
if (s.equals("[/Group]")) {
g = null;
}
if (s.startsWith("BasicLandPercentage")) {
final String[] ss = s.split("\\|");
basicLandPercentage = Integer.parseInt(ss[0].substring("BasicLandPercentage".length() + 1));
if(ss.length > 1)
basicLandSet = ss[1];
}
else if (s.equals("Testing")) {
testing = true;
}
else if (g != null) {
g.cardnames.add(s);
final String[] ss = s.split("\\|");
cardCounts.put(ss[0], 0);
}
}
return groups;
}
}

View File

@@ -1,93 +1,93 @@
package forge.deck;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import forge.interfaces.ICheckBox;
import forge.interfaces.IComboBox;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.util.gui.SOptionPane;
public class DeckImportController {
private final boolean replacingDeck;
private final ICheckBox newEditionCheck, dateTimeCheck, onlyCoreExpCheck;
private final IComboBox<String> monthDropdown;
private final IComboBox<Integer> yearDropdown;
private final List<DeckRecognizer.Token> tokens = new ArrayList<DeckRecognizer.Token>();
public DeckImportController(boolean replacingDeck0, ICheckBox newEditionCheck0, ICheckBox dateTimeCheck0, ICheckBox onlyCoreExpCheck0, IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0) {
replacingDeck = replacingDeck0;
newEditionCheck = newEditionCheck0;
dateTimeCheck = dateTimeCheck0;
onlyCoreExpCheck = onlyCoreExpCheck0;
monthDropdown = monthDropdown0;
yearDropdown = yearDropdown0;
fillDateDropdowns();
}
private void fillDateDropdowns() {
DateFormatSymbols dfs = new DateFormatSymbols();
monthDropdown.removeAllItems();
String[] months = dfs.getMonths();
for (String monthName : months) {
if (!StringUtils.isBlank(monthName)) {
monthDropdown.addItem(monthName);
}
}
int yearNow = Calendar.getInstance().get(Calendar.YEAR);
for (int i = yearNow; i >= 1993; i--) {
yearDropdown.addItem(Integer.valueOf(i));
}
}
public List<DeckRecognizer.Token> parseInput(String input) {
tokens.clear();
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards());
if (dateTimeCheck.isSelected()) {
recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem());
}
String[] lines = input.split("\n");
for (String line : lines) {
tokens.add(recognizer.recognizeLine(line));
}
return tokens;
}
public Deck accept() {
if (tokens.isEmpty()) { return null; }
if (replacingDeck) {
final String warning = "This will replace the contents of your current deck with these cards.\n\nProceed?";
if (!SOptionPane.showConfirmDialog(warning, "Replace Current Deck", "Replace", "Cancel")) {
return null;
}
}
final Deck result = new Deck();
boolean isMain = true;
for (final DeckRecognizer.Token t : tokens) {
final DeckRecognizer.TokenType type = t.getType();
if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) {
isMain = false;
}
if (type != DeckRecognizer.TokenType.KnownCard) {
continue;
}
final PaperCard crd = t.getCard();
if (isMain) {
result.getMain().add(crd, t.getNumber());
}
else {
result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber());
}
}
return result;
}
}
package forge.deck;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import forge.interfaces.ICheckBox;
import forge.interfaces.IComboBox;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.util.gui.SOptionPane;
public class DeckImportController {
private final boolean replacingDeck;
private final ICheckBox newEditionCheck, dateTimeCheck, onlyCoreExpCheck;
private final IComboBox<String> monthDropdown;
private final IComboBox<Integer> yearDropdown;
private final List<DeckRecognizer.Token> tokens = new ArrayList<DeckRecognizer.Token>();
public DeckImportController(boolean replacingDeck0, ICheckBox newEditionCheck0, ICheckBox dateTimeCheck0, ICheckBox onlyCoreExpCheck0, IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0) {
replacingDeck = replacingDeck0;
newEditionCheck = newEditionCheck0;
dateTimeCheck = dateTimeCheck0;
onlyCoreExpCheck = onlyCoreExpCheck0;
monthDropdown = monthDropdown0;
yearDropdown = yearDropdown0;
fillDateDropdowns();
}
private void fillDateDropdowns() {
DateFormatSymbols dfs = new DateFormatSymbols();
monthDropdown.removeAllItems();
String[] months = dfs.getMonths();
for (String monthName : months) {
if (!StringUtils.isBlank(monthName)) {
monthDropdown.addItem(monthName);
}
}
int yearNow = Calendar.getInstance().get(Calendar.YEAR);
for (int i = yearNow; i >= 1993; i--) {
yearDropdown.addItem(Integer.valueOf(i));
}
}
public List<DeckRecognizer.Token> parseInput(String input) {
tokens.clear();
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards());
if (dateTimeCheck.isSelected()) {
recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem());
}
String[] lines = input.split("\n");
for (String line : lines) {
tokens.add(recognizer.recognizeLine(line));
}
return tokens;
}
public Deck accept() {
if (tokens.isEmpty()) { return null; }
if (replacingDeck) {
final String warning = "This will replace the contents of your current deck with these cards.\n\nProceed?";
if (!SOptionPane.showConfirmDialog(warning, "Replace Current Deck", "Replace", "Cancel")) {
return null;
}
}
final Deck result = new Deck();
boolean isMain = true;
for (final DeckRecognizer.Token t : tokens) {
final DeckRecognizer.TokenType type = t.getType();
if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) {
isMain = false;
}
if (type != DeckRecognizer.TokenType.KnownCard) {
continue;
}
final PaperCard crd = t.getCard();
if (isMain) {
result.getMain().add(crd, t.getNumber());
}
else {
result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber());
}
}
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +1,68 @@
package forge.deck;
import forge.model.FModel;
import forge.properties.ForgePreferences;
public enum DeckType {
CUSTOM_DECK ("Custom User Decks"),
CONSTRUCTED_DECK ("Constructed Decks"),
COMMANDER_DECK ("Commander Decks"),
TINY_LEADERS_DECKS ("Tiny Leaders Decks"),
SCHEME_DECKS ("Scheme Decks"),
PLANAR_DECKS ("Planar Decks"),
DRAFT_DECKS ("Draft Decks"),
SEALED_DECKS ("Sealed Decks"),
PRECONSTRUCTED_DECK("Preconstructed Decks"),
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
COLOR_DECK ("Random Color Decks"),
STANDARD_CARDGEN_DECK ("Random Standard Card-themed Decks"),
MODERN_CARDGEN_DECK ("Random Modern Card-themed Decks"),
STANDARD_COLOR_DECK ("Random Standard Color Decks"),
MODERN_COLOR_DECK ("Random Modern Color Decks"),
THEME_DECK ("Random Theme Decks"),
RANDOM_DECK ("Random Decks"),
NET_DECK ("Net Decks"),
NET_COMMANDER_DECK ("Net Commander Decks");
public static DeckType[] ConstructedOptions;
static {
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
ConstructedOptions = new DeckType[]{
DeckType.CUSTOM_DECK,
DeckType.PRECONSTRUCTED_DECK,
DeckType.QUEST_OPPONENT_DECK,
DeckType.COLOR_DECK,
DeckType.STANDARD_COLOR_DECK,
DeckType.STANDARD_CARDGEN_DECK,
DeckType.MODERN_CARDGEN_DECK,
DeckType.MODERN_COLOR_DECK,
DeckType.THEME_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_DECK
};
} else {
ConstructedOptions = new DeckType[]{
DeckType.CUSTOM_DECK,
DeckType.PRECONSTRUCTED_DECK,
DeckType.QUEST_OPPONENT_DECK,
DeckType.COLOR_DECK,
DeckType.STANDARD_COLOR_DECK,
DeckType.MODERN_COLOR_DECK,
DeckType.THEME_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_DECK
};
}
}
private String value;
private DeckType(final String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
package forge.deck;
import forge.model.FModel;
import forge.properties.ForgePreferences;
public enum DeckType {
CUSTOM_DECK ("Custom User Decks"),
CONSTRUCTED_DECK ("Constructed Decks"),
COMMANDER_DECK ("Commander Decks"),
TINY_LEADERS_DECKS ("Tiny Leaders Decks"),
SCHEME_DECKS ("Scheme Decks"),
PLANAR_DECKS ("Planar Decks"),
DRAFT_DECKS ("Draft Decks"),
SEALED_DECKS ("Sealed Decks"),
PRECONSTRUCTED_DECK("Preconstructed Decks"),
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
COLOR_DECK ("Random Color Decks"),
STANDARD_CARDGEN_DECK ("Random Standard Card-themed Decks"),
MODERN_CARDGEN_DECK ("Random Modern Card-themed Decks"),
STANDARD_COLOR_DECK ("Random Standard Color Decks"),
MODERN_COLOR_DECK ("Random Modern Color Decks"),
THEME_DECK ("Random Theme Decks"),
RANDOM_DECK ("Random Decks"),
NET_DECK ("Net Decks"),
NET_COMMANDER_DECK ("Net Commander Decks");
public static DeckType[] ConstructedOptions;
static {
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
ConstructedOptions = new DeckType[]{
DeckType.CUSTOM_DECK,
DeckType.PRECONSTRUCTED_DECK,
DeckType.QUEST_OPPONENT_DECK,
DeckType.COLOR_DECK,
DeckType.STANDARD_COLOR_DECK,
DeckType.STANDARD_CARDGEN_DECK,
DeckType.MODERN_CARDGEN_DECK,
DeckType.MODERN_COLOR_DECK,
DeckType.THEME_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_DECK
};
} else {
ConstructedOptions = new DeckType[]{
DeckType.CUSTOM_DECK,
DeckType.PRECONSTRUCTED_DECK,
DeckType.QUEST_OPPONENT_DECK,
DeckType.COLOR_DECK,
DeckType.STANDARD_COLOR_DECK,
DeckType.MODERN_COLOR_DECK,
DeckType.THEME_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_DECK
};
}
}
private String value;
private DeckType(final String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}

View File

@@ -1,127 +1,127 @@
package forge.deck;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import forge.GuiBase;
import forge.deck.io.DeckSerializer;
import forge.deck.io.DeckStorage;
import forge.download.GuiDownloadZipService;
import forge.game.GameType;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.WaitCallback;
import forge.util.gui.SGuiChoose;
import forge.util.storage.StorageBase;
public class NetDeckCategory extends StorageBase<Deck> {
public static final String PREFIX = "NET_DECK_";
private static Map<String, NetDeckCategory> constructed, commander;
private static Map<String, NetDeckCategory> loadCategories(String filename) {
Map<String, NetDeckCategory> categories = new TreeMap<String, NetDeckCategory>();
if (FileUtil.doesFileExist(filename)) {
List<String> lines = FileUtil.readFile(filename);
for (String line : lines) {
int idx = line.indexOf('|');
if (idx != -1) {
String name = line.substring(0, idx).trim();
String url = line.substring(idx + 1).trim();
categories.put(name, new NetDeckCategory(name, url));
}
}
}
return categories;
}
public static NetDeckCategory selectAndLoad(GameType gameType) {
return selectAndLoad(gameType, null);
}
public static NetDeckCategory selectAndLoad(GameType gameType, String name) {
Map<String, NetDeckCategory> categories;
switch (gameType) {
case Constructed:
case Gauntlet:
if (constructed == null) {
constructed = loadCategories(ForgeConstants.NET_DECKS_LIST_FILE);
}
categories = constructed;
break;
case Commander:
if (commander == null) {
commander = loadCategories(ForgeConstants.NET_DECKS_COMMANDER_LIST_FILE);
}
categories = commander;
break;
default:
return null;
}
if (name != null) {
NetDeckCategory category = categories.get(name);
if (category != null && category.map.isEmpty()) {
//if name passed in, try to load decks from current cached files
File downloadDir = new File(category.getFullPath());
if (downloadDir.exists()) {
for (File file : downloadDir.listFiles(DeckStorage.DCK_FILE_FILTER)) {
Deck deck = DeckSerializer.fromFile(file);
if (deck != null) {
category.map.put(deck.getName(), deck);
}
}
}
}
return category;
}
final NetDeckCategory c = SGuiChoose.oneOrNone("Select a Net Deck category", categories.values());
if (c == null) { return null; }
if (c.map.isEmpty()) { //only download decks once per session
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
@Override
public void run() {
String downloadLoc = c.getFullPath();
GuiBase.getInterface().download(new GuiDownloadZipService(c.getName(), "decks", c.getUrl(), downloadLoc, downloadLoc, null) {
@Override
protected void copyInputStream(InputStream in, String outPath) throws IOException {
super.copyInputStream(in, outPath);
Deck deck = DeckSerializer.fromFile(new File(outPath));
if (deck != null) {
c.map.put(deck.getName(), deck);
}
}
}, this);
}
};
if (!callback.invokeAndWait()) { return null; } //wait for download to finish
}
return c;
}
private final String url;
private NetDeckCategory(String name0, String url0) {
super(name0, ForgeConstants.DECK_NET_DIR + name0, new HashMap<String, Deck>());
url = url0;
}
public String getUrl() {
return url;
}
public String getDeckType() {
return "Net Decks - " + name;
}
@Override
public String toString() {
return name;
}
}
package forge.deck;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import forge.GuiBase;
import forge.deck.io.DeckSerializer;
import forge.deck.io.DeckStorage;
import forge.download.GuiDownloadZipService;
import forge.game.GameType;
import forge.properties.ForgeConstants;
import forge.util.FileUtil;
import forge.util.WaitCallback;
import forge.util.gui.SGuiChoose;
import forge.util.storage.StorageBase;
public class NetDeckCategory extends StorageBase<Deck> {
public static final String PREFIX = "NET_DECK_";
private static Map<String, NetDeckCategory> constructed, commander;
private static Map<String, NetDeckCategory> loadCategories(String filename) {
Map<String, NetDeckCategory> categories = new TreeMap<String, NetDeckCategory>();
if (FileUtil.doesFileExist(filename)) {
List<String> lines = FileUtil.readFile(filename);
for (String line : lines) {
int idx = line.indexOf('|');
if (idx != -1) {
String name = line.substring(0, idx).trim();
String url = line.substring(idx + 1).trim();
categories.put(name, new NetDeckCategory(name, url));
}
}
}
return categories;
}
public static NetDeckCategory selectAndLoad(GameType gameType) {
return selectAndLoad(gameType, null);
}
public static NetDeckCategory selectAndLoad(GameType gameType, String name) {
Map<String, NetDeckCategory> categories;
switch (gameType) {
case Constructed:
case Gauntlet:
if (constructed == null) {
constructed = loadCategories(ForgeConstants.NET_DECKS_LIST_FILE);
}
categories = constructed;
break;
case Commander:
if (commander == null) {
commander = loadCategories(ForgeConstants.NET_DECKS_COMMANDER_LIST_FILE);
}
categories = commander;
break;
default:
return null;
}
if (name != null) {
NetDeckCategory category = categories.get(name);
if (category != null && category.map.isEmpty()) {
//if name passed in, try to load decks from current cached files
File downloadDir = new File(category.getFullPath());
if (downloadDir.exists()) {
for (File file : downloadDir.listFiles(DeckStorage.DCK_FILE_FILTER)) {
Deck deck = DeckSerializer.fromFile(file);
if (deck != null) {
category.map.put(deck.getName(), deck);
}
}
}
}
return category;
}
final NetDeckCategory c = SGuiChoose.oneOrNone("Select a Net Deck category", categories.values());
if (c == null) { return null; }
if (c.map.isEmpty()) { //only download decks once per session
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
@Override
public void run() {
String downloadLoc = c.getFullPath();
GuiBase.getInterface().download(new GuiDownloadZipService(c.getName(), "decks", c.getUrl(), downloadLoc, downloadLoc, null) {
@Override
protected void copyInputStream(InputStream in, String outPath) throws IOException {
super.copyInputStream(in, outPath);
Deck deck = DeckSerializer.fromFile(new File(outPath));
if (deck != null) {
c.map.put(deck.getName(), deck);
}
}
}, this);
}
};
if (!callback.invokeAndWait()) { return null; } //wait for download to finish
}
return c;
}
private final String url;
private NetDeckCategory(String name0, String url0) {
super(name0, ForgeConstants.DECK_NET_DIR + name0, new HashMap<String, Deck>());
url = url0;
}
public String getUrl() {
return url;
}
public String getDeckType() {
return "Net Decks - " + name;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -1,188 +1,188 @@
package forge.deck;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.game.GameType;
import forge.game.IHasGameType;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.util.Aggregates;
public class RandomDeckGenerator extends DeckProxy implements Comparable<RandomDeckGenerator> {
private enum RandomDeckType {
Generated,
User,
Favorite
}
public static List<DeckProxy> getRandomDecks(final IHasGameType lstDecks0, final boolean isAi0) {
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
decks.add(new RandomDeckGenerator("Random Generated Deck", RandomDeckType.Generated, lstDecks0, isAi0));
decks.add(new RandomDeckGenerator("Random User Deck", RandomDeckType.User, lstDecks0, isAi0));
decks.add(new RandomDeckGenerator("Random Favorite Deck", RandomDeckType.Favorite, lstDecks0, isAi0));
return decks;
}
public static Deck getRandomUserDeck(final IHasGameType lstDecks0, final boolean isAi0) {
RandomDeckGenerator generator = new RandomDeckGenerator(null, RandomDeckType.User, lstDecks0, isAi0);
return generator.getDeck();
}
private final String name;
private final RandomDeckType type;
private final IHasGameType lstDecks;
private final boolean isAi;
private RandomDeckGenerator(final String name0, final RandomDeckType type0, final IHasGameType lstDecks0, final boolean isAi0) {
super();
name = name0;
type = type0;
lstDecks = lstDecks0;
isAi = isAi0;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final RandomDeckGenerator d) {
return Integer.compare(type.ordinal(), d.type.ordinal());
}
@Override
public Deck getDeck() {
switch (type) {
case Generated:
return getGeneratedDeck();
case User:
return getUserDeck();
default:
return getFavoriteDeck();
}
}
private Deck getGeneratedDeck() {
switch (lstDecks.getGameType()) {
case Commander:
return DeckgenUtil.generateCommanderDeck(isAi, GameType.Commander);
case TinyLeaders:
return DeckgenUtil.generateCommanderDeck(isAi, GameType.TinyLeaders);
case Archenemy:
return DeckgenUtil.generateSchemeDeck();
case Planechase:
return DeckgenUtil.generatePlanarDeck();
default:
while (true) {
switch (Aggregates.random(DeckType.ConstructedOptions)) {
case PRECONSTRUCTED_DECK:
return Aggregates.random(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())).getDeck();
case QUEST_OPPONENT_DECK:
return Aggregates.random(DeckProxy.getAllQuestEventAndChallenges()).getDeck();
case COLOR_DECK:
List<String> colors = new ArrayList<String>();
int count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, null, isAi);
case STANDARD_CARDGEN_DECK:
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),isAi);
case MODERN_CARDGEN_DECK:
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),isAi);
case STANDARD_COLOR_DECK:
colors = new ArrayList<String>();
count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getStandard().getFilterPrinted(), isAi);
case MODERN_COLOR_DECK:
colors = new ArrayList<String>();
count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getModern().getFilterPrinted(), isAi);
case THEME_DECK:
return Aggregates.random(DeckProxy.getAllThemeDecks()).getDeck();
default:
continue;
}
}
}
}
private Deck getUserDeck() {
Iterable<DeckProxy> decks;
final GameType gameType = lstDecks.getGameType();
switch (gameType) {
case Commander:
decks = DeckProxy.getAllCommanderDecks(DeckFormat.Commander.isLegalDeckPredicate());
break;
case TinyLeaders:
decks = DeckProxy.getAllTinyLeadersDecks(DeckFormat.TinyLeaders.isLegalDeckPredicate());
break;
case Archenemy:
decks = DeckProxy.getAllSchemeDecks(DeckFormat.Archenemy.isLegalDeckPredicate());
break;
case Planechase:
decks = DeckProxy.getAllPlanarDecks(DeckFormat.Planechase.isLegalDeckPredicate());
break;
default:
decks = DeckProxy.getAllConstructedDecks(gameType.getDeckFormat().isLegalDeckPredicate());
break;
}
if (Iterables.isEmpty(decks)) {
return getGeneratedDeck(); //fall back to generated deck if no decks in filtered list
}
return Aggregates.random(decks).getDeck();
}
private Deck getFavoriteDeck() {
Iterable<DeckProxy> decks;
switch (lstDecks.getGameType()) {
case Commander:
decks = DeckProxy.getAllCommanderDecks();
break;
case TinyLeaders:
decks = DeckProxy.getAllTinyLeadersDecks();
break;
case Archenemy:
decks = DeckProxy.getAllSchemeDecks();
break;
case Planechase:
decks = DeckProxy.getAllPlanarDecks();
break;
default:
decks = DeckProxy.getAllConstructedDecks();
break;
}
decks = Iterables.filter(decks, new Predicate<DeckProxy>() {
@Override public boolean apply(final DeckProxy deck) {
return deck.isFavoriteDeck();
}
});
if (Iterables.isEmpty(decks)) {
return getGeneratedDeck(); //fall back to generated deck if no favorite decks
}
return Aggregates.random(decks).getDeck();
}
@Override
public boolean isGeneratedDeck() {
return true;
}
}
package forge.deck;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.game.GameType;
import forge.game.IHasGameType;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.util.Aggregates;
public class RandomDeckGenerator extends DeckProxy implements Comparable<RandomDeckGenerator> {
private enum RandomDeckType {
Generated,
User,
Favorite
}
public static List<DeckProxy> getRandomDecks(final IHasGameType lstDecks0, final boolean isAi0) {
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
decks.add(new RandomDeckGenerator("Random Generated Deck", RandomDeckType.Generated, lstDecks0, isAi0));
decks.add(new RandomDeckGenerator("Random User Deck", RandomDeckType.User, lstDecks0, isAi0));
decks.add(new RandomDeckGenerator("Random Favorite Deck", RandomDeckType.Favorite, lstDecks0, isAi0));
return decks;
}
public static Deck getRandomUserDeck(final IHasGameType lstDecks0, final boolean isAi0) {
RandomDeckGenerator generator = new RandomDeckGenerator(null, RandomDeckType.User, lstDecks0, isAi0);
return generator.getDeck();
}
private final String name;
private final RandomDeckType type;
private final IHasGameType lstDecks;
private final boolean isAi;
private RandomDeckGenerator(final String name0, final RandomDeckType type0, final IHasGameType lstDecks0, final boolean isAi0) {
super();
name = name0;
type = type0;
lstDecks = lstDecks0;
isAi = isAi0;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(final RandomDeckGenerator d) {
return Integer.compare(type.ordinal(), d.type.ordinal());
}
@Override
public Deck getDeck() {
switch (type) {
case Generated:
return getGeneratedDeck();
case User:
return getUserDeck();
default:
return getFavoriteDeck();
}
}
private Deck getGeneratedDeck() {
switch (lstDecks.getGameType()) {
case Commander:
return DeckgenUtil.generateCommanderDeck(isAi, GameType.Commander);
case TinyLeaders:
return DeckgenUtil.generateCommanderDeck(isAi, GameType.TinyLeaders);
case Archenemy:
return DeckgenUtil.generateSchemeDeck();
case Planechase:
return DeckgenUtil.generatePlanarDeck();
default:
while (true) {
switch (Aggregates.random(DeckType.ConstructedOptions)) {
case PRECONSTRUCTED_DECK:
return Aggregates.random(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())).getDeck();
case QUEST_OPPONENT_DECK:
return Aggregates.random(DeckProxy.getAllQuestEventAndChallenges()).getDeck();
case COLOR_DECK:
List<String> colors = new ArrayList<String>();
int count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, null, isAi);
case STANDARD_CARDGEN_DECK:
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),isAi);
case MODERN_CARDGEN_DECK:
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),isAi);
case STANDARD_COLOR_DECK:
colors = new ArrayList<String>();
count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getStandard().getFilterPrinted(), isAi);
case MODERN_COLOR_DECK:
colors = new ArrayList<String>();
count = Aggregates.randomInt(1, 3);
for (int i = 1; i <= count; i++) {
colors.add("Random " + i);
}
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getModern().getFilterPrinted(), isAi);
case THEME_DECK:
return Aggregates.random(DeckProxy.getAllThemeDecks()).getDeck();
default:
continue;
}
}
}
}
private Deck getUserDeck() {
Iterable<DeckProxy> decks;
final GameType gameType = lstDecks.getGameType();
switch (gameType) {
case Commander:
decks = DeckProxy.getAllCommanderDecks(DeckFormat.Commander.isLegalDeckPredicate());
break;
case TinyLeaders:
decks = DeckProxy.getAllTinyLeadersDecks(DeckFormat.TinyLeaders.isLegalDeckPredicate());
break;
case Archenemy:
decks = DeckProxy.getAllSchemeDecks(DeckFormat.Archenemy.isLegalDeckPredicate());
break;
case Planechase:
decks = DeckProxy.getAllPlanarDecks(DeckFormat.Planechase.isLegalDeckPredicate());
break;
default:
decks = DeckProxy.getAllConstructedDecks(gameType.getDeckFormat().isLegalDeckPredicate());
break;
}
if (Iterables.isEmpty(decks)) {
return getGeneratedDeck(); //fall back to generated deck if no decks in filtered list
}
return Aggregates.random(decks).getDeck();
}
private Deck getFavoriteDeck() {
Iterable<DeckProxy> decks;
switch (lstDecks.getGameType()) {
case Commander:
decks = DeckProxy.getAllCommanderDecks();
break;
case TinyLeaders:
decks = DeckProxy.getAllTinyLeadersDecks();
break;
case Archenemy:
decks = DeckProxy.getAllSchemeDecks();
break;
case Planechase:
decks = DeckProxy.getAllPlanarDecks();
break;
default:
decks = DeckProxy.getAllConstructedDecks();
break;
}
decks = Iterables.filter(decks, new Predicate<DeckProxy>() {
@Override public boolean apply(final DeckProxy deck) {
return deck.isFavoriteDeck();
}
});
if (Iterables.isEmpty(decks)) {
return getGeneratedDeck(); //fall back to generated deck if no favorite decks
}
return Aggregates.random(decks).getDeck();
}
@Override
public boolean isGeneratedDeck() {
return true;
}
}

View File

@@ -1,67 +1,67 @@
package forge.deck.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.game.GameFormat;
import forge.item.PaperCard;
import forge.properties.ForgeConstants;
/**
* Created by maustin on 11/05/2017.
*/
public class CardThemedMatrixIO {
/** suffix for all gauntlet data files */
public static final String SUFFIX_DATA = ".dat";
public static void saveMatrix(GameFormat format, HashMap<String,List<Map.Entry<PaperCard,Integer>>> map){
File file = getMatrixFile(format);
ObjectOutputStream s = null;
try {
FileOutputStream f = new FileOutputStream(file);
s = new ObjectOutputStream(f);
s.writeObject(map);
s.close();
} catch (IOException e) {
System.out.println("Error writing matrix data: " + e);
} finally {
if(s!=null) {
try {
s.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> loadMatrix(GameFormat format){
try {
FileInputStream fin = new FileInputStream(getMatrixFile(format));
ObjectInputStream s = new ObjectInputStream(fin);
HashMap<String, List<Map.Entry<PaperCard,Integer>>> matrix = (HashMap<String, List<Map.Entry<PaperCard,Integer>>>) s.readObject();
s.close();
return matrix;
}catch (Exception e){
System.out.println("Error reading matrix data: " + e);
return null;
}
}
public static File getMatrixFile(final String name) {
return new File(ForgeConstants.DECK_GEN_DIR, name + SUFFIX_DATA);
}
public static File getMatrixFile(final GameFormat gf) {
return getMatrixFile(gf.getName());
}
}
package forge.deck.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.game.GameFormat;
import forge.item.PaperCard;
import forge.properties.ForgeConstants;
/**
* Created by maustin on 11/05/2017.
*/
public class CardThemedMatrixIO {
/** suffix for all gauntlet data files */
public static final String SUFFIX_DATA = ".dat";
public static void saveMatrix(GameFormat format, HashMap<String,List<Map.Entry<PaperCard,Integer>>> map){
File file = getMatrixFile(format);
ObjectOutputStream s = null;
try {
FileOutputStream f = new FileOutputStream(file);
s = new ObjectOutputStream(f);
s.writeObject(map);
s.close();
} catch (IOException e) {
System.out.println("Error writing matrix data: " + e);
} finally {
if(s!=null) {
try {
s.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> loadMatrix(GameFormat format){
try {
FileInputStream fin = new FileInputStream(getMatrixFile(format));
ObjectInputStream s = new ObjectInputStream(fin);
HashMap<String, List<Map.Entry<PaperCard,Integer>>> matrix = (HashMap<String, List<Map.Entry<PaperCard,Integer>>>) s.readObject();
s.close();
return matrix;
}catch (Exception e){
System.out.println("Error reading matrix data: " + e);
return null;
}
}
public static File getMatrixFile(final String name) {
return new File(ForgeConstants.DECK_GEN_DIR, name + SUFFIX_DATA);
}
public static File getMatrixFile(final GameFormat gf) {
return getMatrixFile(gf.getName());
}
}

View File

@@ -1,176 +1,176 @@
package forge.deck.io;
import forge.deck.DeckProxy;
import forge.properties.ForgeConstants;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual decks
*
*/
public class DeckPreferences {
private static String currentDeck = "", draftDeck = "", sealedDeck = "", commanderDeck = "", tinyLeadersDeck = "", planarDeck = "", schemeDeck = "";
private static Map<String, DeckPreferences> allPrefs = new HashMap<String, DeckPreferences>();
public static String getCurrentDeck() {
return currentDeck;
}
public static void setCurrentDeck(String currentDeck0) {
if (currentDeck.equals(currentDeck0)) { return; }
currentDeck = currentDeck0;
save();
}
public static String getDraftDeck() {
return draftDeck;
}
public static void setDraftDeck(String draftDeck0) {
if (draftDeck.equals(draftDeck0)) { return; }
draftDeck = draftDeck0;
save();
}
public static String getSealedDeck() {
return sealedDeck;
}
public static void setSealedDeck(String sealedDeck0) {
if (sealedDeck.equals(sealedDeck0)) { return; }
sealedDeck = sealedDeck0;
save();
}
public static String getCommanderDeck() {
return commanderDeck;
}
public static void setCommanderDeck(String commanderDeck0) {
if (commanderDeck.equals(commanderDeck0)) { return; }
commanderDeck = commanderDeck0;
save();
}
public static String getTinyLeadersDeck() {
return tinyLeadersDeck;
}
public static void setTinyLeadersDeck(String tinyLeadersDeck0) {
if (tinyLeadersDeck.equals(tinyLeadersDeck0)) { return; }
tinyLeadersDeck = tinyLeadersDeck0;
save();
}
public static String getPlanarDeck() {
return planarDeck;
}
public static void setPlanarDeck(String planarDeck0) {
if (planarDeck.equals(planarDeck0)) { return; }
planarDeck = planarDeck0;
save();
}
public static String getSchemeDeck() {
return schemeDeck;
}
public static void setSchemeDeck(String schemeDeck0) {
if (schemeDeck.equals(schemeDeck0)) { return; }
schemeDeck = schemeDeck0;
save();
}
public static DeckPreferences getPrefs(DeckProxy deck) {
String key = deck.getUniqueKey();
DeckPreferences prefs = allPrefs.get(key);
if (prefs == null) {
prefs = new DeckPreferences();
allPrefs.put(key, prefs);
}
return prefs;
}
public static void load() {
allPrefs.clear();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.DECK_PREFS_FILE));
final Element root = (Element)document.getElementsByTagName("preferences").item(0);
currentDeck = root.getAttribute("currentDeck");
draftDeck = root.getAttribute("draftDeck");
sealedDeck = root.getAttribute("sealedDeck");
commanderDeck = root.getAttribute("commanderDeck");
tinyLeadersDeck = root.getAttribute("tinyLeadersDeck");
planarDeck = root.getAttribute("planarDeck");
schemeDeck = root.getAttribute("schemeDeck");
final NodeList cards = document.getElementsByTagName("deck");
for (int i = 0; i < cards.getLength(); i++) {
final DeckPreferences prefs = new DeckPreferences();
final Element el = (Element)cards.item(i);
allPrefs.put(el.getAttribute("key"), prefs);
prefs.starCount = XmlUtil.getIntAttribute(el, "stars");
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "decks");
root.setAttribute("currentDeck", currentDeck);
root.setAttribute("draftDeck", draftDeck);
root.setAttribute("sealedDeck", sealedDeck);
root.setAttribute("commanderDeck", commanderDeck);
root.setAttribute("tinyLeadersDeck", tinyLeadersDeck);
root.setAttribute("planarDeck", planarDeck);
root.setAttribute("schemeDeck", schemeDeck);
document.appendChild(root);
for (Map.Entry<String, DeckPreferences> entry : allPrefs.entrySet()) {
if (entry.getValue().starCount > 0) {
Element deck = document.createElement("deck");
deck.setAttribute("key", entry.getKey());
deck.setAttribute("stars", String.valueOf(entry.getValue().starCount));
root.appendChild(deck);
}
}
XmlUtil.saveDocument(document, ForgeConstants.DECK_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
private int starCount;
private DeckPreferences() {
}
public int getStarCount() {
return this.starCount;
}
public void setStarCount(int starCount0) {
if (this.starCount == starCount0) { return; }
this.starCount = starCount0;
save();
}
package forge.deck.io;
import forge.deck.DeckProxy;
import forge.properties.ForgeConstants;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual decks
*
*/
public class DeckPreferences {
private static String currentDeck = "", draftDeck = "", sealedDeck = "", commanderDeck = "", tinyLeadersDeck = "", planarDeck = "", schemeDeck = "";
private static Map<String, DeckPreferences> allPrefs = new HashMap<String, DeckPreferences>();
public static String getCurrentDeck() {
return currentDeck;
}
public static void setCurrentDeck(String currentDeck0) {
if (currentDeck.equals(currentDeck0)) { return; }
currentDeck = currentDeck0;
save();
}
public static String getDraftDeck() {
return draftDeck;
}
public static void setDraftDeck(String draftDeck0) {
if (draftDeck.equals(draftDeck0)) { return; }
draftDeck = draftDeck0;
save();
}
public static String getSealedDeck() {
return sealedDeck;
}
public static void setSealedDeck(String sealedDeck0) {
if (sealedDeck.equals(sealedDeck0)) { return; }
sealedDeck = sealedDeck0;
save();
}
public static String getCommanderDeck() {
return commanderDeck;
}
public static void setCommanderDeck(String commanderDeck0) {
if (commanderDeck.equals(commanderDeck0)) { return; }
commanderDeck = commanderDeck0;
save();
}
public static String getTinyLeadersDeck() {
return tinyLeadersDeck;
}
public static void setTinyLeadersDeck(String tinyLeadersDeck0) {
if (tinyLeadersDeck.equals(tinyLeadersDeck0)) { return; }
tinyLeadersDeck = tinyLeadersDeck0;
save();
}
public static String getPlanarDeck() {
return planarDeck;
}
public static void setPlanarDeck(String planarDeck0) {
if (planarDeck.equals(planarDeck0)) { return; }
planarDeck = planarDeck0;
save();
}
public static String getSchemeDeck() {
return schemeDeck;
}
public static void setSchemeDeck(String schemeDeck0) {
if (schemeDeck.equals(schemeDeck0)) { return; }
schemeDeck = schemeDeck0;
save();
}
public static DeckPreferences getPrefs(DeckProxy deck) {
String key = deck.getUniqueKey();
DeckPreferences prefs = allPrefs.get(key);
if (prefs == null) {
prefs = new DeckPreferences();
allPrefs.put(key, prefs);
}
return prefs;
}
public static void load() {
allPrefs.clear();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.DECK_PREFS_FILE));
final Element root = (Element)document.getElementsByTagName("preferences").item(0);
currentDeck = root.getAttribute("currentDeck");
draftDeck = root.getAttribute("draftDeck");
sealedDeck = root.getAttribute("sealedDeck");
commanderDeck = root.getAttribute("commanderDeck");
tinyLeadersDeck = root.getAttribute("tinyLeadersDeck");
planarDeck = root.getAttribute("planarDeck");
schemeDeck = root.getAttribute("schemeDeck");
final NodeList cards = document.getElementsByTagName("deck");
for (int i = 0; i < cards.getLength(); i++) {
final DeckPreferences prefs = new DeckPreferences();
final Element el = (Element)cards.item(i);
allPrefs.put(el.getAttribute("key"), prefs);
prefs.starCount = XmlUtil.getIntAttribute(el, "stars");
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "decks");
root.setAttribute("currentDeck", currentDeck);
root.setAttribute("draftDeck", draftDeck);
root.setAttribute("sealedDeck", sealedDeck);
root.setAttribute("commanderDeck", commanderDeck);
root.setAttribute("tinyLeadersDeck", tinyLeadersDeck);
root.setAttribute("planarDeck", planarDeck);
root.setAttribute("schemeDeck", schemeDeck);
document.appendChild(root);
for (Map.Entry<String, DeckPreferences> entry : allPrefs.entrySet()) {
if (entry.getValue().starCount > 0) {
Element deck = document.createElement("deck");
deck.setAttribute("key", entry.getKey());
deck.setAttribute("stars", String.valueOf(entry.getValue().starCount));
root.appendChild(deck);
}
}
XmlUtil.saveDocument(document, ForgeConstants.DECK_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
private int starCount;
private DeckPreferences() {
}
public int getStarCount() {
return this.starCount;
}
public void setStarCount(int starCount0) {
if (this.starCount == starCount0) { return; }
this.starCount = starCount0;
save();
}
}

View File

@@ -1,57 +1,57 @@
package forge.deck.io;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.LobbyPlayer;
import forge.ai.LobbyPlayerAi;
import forge.game.GameOutcome;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
@SuppressWarnings("unused")
public class DeckRecords {
private static final Map<String, DeckRecords> recordLookup = new HashMap<String, DeckRecords>();
public static void recordMatchOutcome(Match match) {
for (RegisteredPlayer p1 : match.getPlayers()) {
for (RegisteredPlayer p2 : match.getPlayers()) {
if (p1 != p2) {
}
}
}
}
private final List<DeckMatch> matches = new ArrayList<DeckMatch>();
public void addMatch(Match match, LobbyPlayer player) {
matches.add(new DeckMatch(match, player));
}
private static class DeckMatch {
private final long timestamp;
private final boolean isAi;
private final int results;
private DeckMatch(Match match, LobbyPlayer player) {
timestamp = new Date().getTime();
isAi = (player instanceof LobbyPlayerAi);
int results0 = 0;
int bit = 1;
for (GameOutcome outcome : match.getOutcomes()) {
if (outcome.isWinner(player)) {
results0 += bit;
}
else if (outcome.isDraw()) {
}
bit *= 2;
}
results = results0;
}
}
}
package forge.deck.io;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.LobbyPlayer;
import forge.ai.LobbyPlayerAi;
import forge.game.GameOutcome;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
@SuppressWarnings("unused")
public class DeckRecords {
private static final Map<String, DeckRecords> recordLookup = new HashMap<String, DeckRecords>();
public static void recordMatchOutcome(Match match) {
for (RegisteredPlayer p1 : match.getPlayers()) {
for (RegisteredPlayer p2 : match.getPlayers()) {
if (p1 != p2) {
}
}
}
}
private final List<DeckMatch> matches = new ArrayList<DeckMatch>();
public void addMatch(Match match, LobbyPlayer player) {
matches.add(new DeckMatch(match, player));
}
private static class DeckMatch {
private final long timestamp;
private final boolean isAi;
private final int results;
private DeckMatch(Match match, LobbyPlayer player) {
timestamp = new Date().getTime();
isAi = (player instanceof LobbyPlayerAi);
int results0 = 0;
int bit = 1;
for (GameOutcome outcome : match.getOutcomes()) {
if (outcome.isWinner(player)) {
results0 += bit;
}
else if (outcome.isDraw()) {
}
bit *= 2;
}
results = results0;
}
}
}

View File

@@ -1,67 +1,67 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.ImageUtil;
import java.util.Map;
import java.util.TreeMap;
public class GuiDownloadPicturesLQ extends GuiDownloadService {
@Override
public String getTitle() {
return "Download LQ Card Pictures";
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
addDLObject(c, downloads, false);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(c, downloads, true);
}
}
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
addDLObject(c, downloads, false);
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private static void addDLObject(final PaperCard c, final Map<String, String> downloads, final boolean backFace) {
String[] result = ImageUtil.getDownloadUrlAndDestination(ForgeConstants.CACHE_CARD_PICS_DIR, c, backFace);
if (result == null) {
return;
}
final String urlToDownload = result[0];
final String destPath = result[1];
if (downloads.containsKey(destPath)) {
return;
}
downloads.put(destPath, urlToDownload);
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.ImageUtil;
import java.util.Map;
import java.util.TreeMap;
public class GuiDownloadPicturesLQ extends GuiDownloadService {
@Override
public String getTitle() {
return "Download LQ Card Pictures";
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
addDLObject(c, downloads, false);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(c, downloads, true);
}
}
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
addDLObject(c, downloads, false);
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private static void addDLObject(final PaperCard c, final Map<String, String> downloads, final boolean backFace) {
String[] result = ImageUtil.getDownloadUrlAndDestination(ForgeConstants.CACHE_CARD_PICS_DIR, c, backFace);
if (result == null) {
return;
}
final String urlToDownload = result[0];
final String destPath = result[1];
if (downloads.containsKey(destPath)) {
return;
}
downloads.put(destPath, urlToDownload);
}
}

View File

@@ -1,36 +1,36 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import forge.properties.ForgeConstants;
public class GuiDownloadPrices extends GuiDownloadService {
@Override
public String getTitle() {
return "Download Card Prices";
}
@Override
protected Map<String, String> getNeededFiles() {
return ImmutableMap.of(ForgeConstants.QUEST_CARD_PRICE_FILE, ForgeConstants.URL_PRICE_DOWNLOAD);
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import forge.properties.ForgeConstants;
public class GuiDownloadPrices extends GuiDownloadService {
@Override
public String getTitle() {
return "Download Card Prices";
}
@Override
protected Map<String, String> getNeededFiles() {
return ImmutableMap.of(ForgeConstants.QUEST_CARD_PRICE_FILE, ForgeConstants.URL_PRICE_DOWNLOAD);
}
}

View File

@@ -1,113 +1,113 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import com.google.common.collect.Iterables;
import forge.StaticData;
import forge.card.CardEdition;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.HttpUtil;
import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.*;
public class GuiDownloadSetPicturesLQ extends GuiDownloadService {
@Override
public String getTitle() {
return "Download LQ Set Pictures";
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final Map<String, String> setMapping = new HashMap<>();
final HashSet<String> existingSets = retrieveManifestDirectory();
final HashSet<String> missingSets = new HashSet<>();
for (final PaperCard c : Iterables.concat(FModel.getMagicDb().getCommonCards().getAllCards(), FModel.getMagicDb().getVariantCards().getAllCards())) {
final String setCode3 = c.getEdition();
if (!setMapping.containsKey(setCode3)) {
setMapping.put(setCode3, StaticData.instance().getEditions().getCode2ByCode(setCode3));
}
final String setCode2 = setMapping.get(setCode3);
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
// we don't want cards from unknown sets
continue;
}
if (!(existingSets.contains(setCode3) || existingSets.contains(setCode2))) {
// If set doesn't exist on server, don't try to download cards for it
if (!missingSets.contains(setCode3)) {
missingSets.add(setCode3);
System.out.println(setCode3 + " not found on server. Ignoring downloads for this set.");
}
continue;
}
addDLObject(ImageUtil.getDownloadUrl(c, false), ImageUtil.getImageKey(c, false, true), downloads);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(ImageUtil.getDownloadUrl(c, true), ImageUtil.getImageKey(c, true, true), downloads);
}
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private static void addDLObject(final String urlPath, final String filename, final Map<String, String> downloads) {
final File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
// System.out.println(filename);
if (!destFile.exists()) {
downloads.put(destFile.getAbsolutePath(), ForgeConstants.URL_PIC_DOWNLOAD + urlPath);
}
}
private HashSet<String> retrieveManifestDirectory() {
String manifestUrl = ForgeConstants.URL_PIC_DOWNLOAD;
HashSet<String> existingSets = new HashSet<>();
String response = HttpUtil.getURL(manifestUrl);
if (response == null) return null;
String[] strings = response.split("<a href=\"");
for (String s : strings) {
int idx = s.indexOf('/');
if (!Character.isLetterOrDigit(s.charAt(0)) || idx > 4 || idx == -1) {
continue;
}
String set = s.substring(0, idx);
existingSets.add(set);
}
return existingSets;
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import com.google.common.collect.Iterables;
import forge.StaticData;
import forge.card.CardEdition;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.HttpUtil;
import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.*;
public class GuiDownloadSetPicturesLQ extends GuiDownloadService {
@Override
public String getTitle() {
return "Download LQ Set Pictures";
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final Map<String, String> setMapping = new HashMap<>();
final HashSet<String> existingSets = retrieveManifestDirectory();
final HashSet<String> missingSets = new HashSet<>();
for (final PaperCard c : Iterables.concat(FModel.getMagicDb().getCommonCards().getAllCards(), FModel.getMagicDb().getVariantCards().getAllCards())) {
final String setCode3 = c.getEdition();
if (!setMapping.containsKey(setCode3)) {
setMapping.put(setCode3, StaticData.instance().getEditions().getCode2ByCode(setCode3));
}
final String setCode2 = setMapping.get(setCode3);
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
// we don't want cards from unknown sets
continue;
}
if (!(existingSets.contains(setCode3) || existingSets.contains(setCode2))) {
// If set doesn't exist on server, don't try to download cards for it
if (!missingSets.contains(setCode3)) {
missingSets.add(setCode3);
System.out.println(setCode3 + " not found on server. Ignoring downloads for this set.");
}
continue;
}
addDLObject(ImageUtil.getDownloadUrl(c, false), ImageUtil.getImageKey(c, false, true), downloads);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(ImageUtil.getDownloadUrl(c, true), ImageUtil.getImageKey(c, true, true), downloads);
}
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private static void addDLObject(final String urlPath, final String filename, final Map<String, String> downloads) {
final File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
// System.out.println(filename);
if (!destFile.exists()) {
downloads.put(destFile.getAbsolutePath(), ForgeConstants.URL_PIC_DOWNLOAD + urlPath);
}
}
private HashSet<String> retrieveManifestDirectory() {
String manifestUrl = ForgeConstants.URL_PIC_DOWNLOAD;
HashSet<String> existingSets = new HashSet<>();
String response = HttpUtil.getURL(manifestUrl);
if (response == null) return null;
String[] strings = response.split("<a href=\"");
for (String s : strings) {
int idx = s.indexOf('/');
if (!Character.isLetterOrDigit(s.charAt(0)) || idx > 4 || idx == -1) {
continue;
}
String set = s.substring(0, idx);
existingSets.add(set);
}
return existingSets;
}
}

View File

@@ -1,224 +1,224 @@
package forge.download;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.esotericsoftware.minlog.Log;
import com.google.common.io.Files;
import forge.FThreads;
import forge.GuiBase;
import forge.interfaces.IProgressBar;
import forge.util.FileUtil;
public class GuiDownloadZipService extends GuiDownloadService {
private final String name, desc, sourceUrl, destFolder, deleteFolder;
private int filesExtracted;
public GuiDownloadZipService(final String name0, final String desc0, final String sourceUrl0, final String destFolder0, final String deleteFolder0, final IProgressBar progressBar0) {
name = name0;
desc = desc0;
sourceUrl = sourceUrl0;
destFolder = destFolder0;
deleteFolder = deleteFolder0;
progressBar = progressBar0;
}
@Override
public String getTitle() {
return "Download " + name;
}
@Override
protected String getStartOverrideDesc() {
return desc;
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> files = new HashMap<String, String>();
files.put("_", "_");
return files; //not needed by zip service, so just return map of size 1
}
@Override
public final void run() {
downloadAndUnzip();
if (!cancel) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
progressBar.setDescription(filesExtracted + " " + desc + " extracted");
finish();
}
});
}
}
public void downloadAndUnzip() {
filesExtracted = 0;
String zipFilename = download("temp.zip");
if (zipFilename == null) { return; }
//if assets.zip downloaded successfully, unzip into destination folder
try {
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
if (deleteFolder != null) {
final File deleteDir = new File(deleteFolder);
if (deleteDir.exists()) {
//attempt to delete previous res directory if to be rebuilt
progressBar.reset();
progressBar.setDescription("Deleting old " + desc + "...");
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
final String oldZipFilename = zipFilename;
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
Files.move(new File(oldZipFilename), new File(zipFilename));
}
FileUtil.deleteDirectory(deleteDir);
}
}
final ZipFile zipFile = new ZipFile(zipFilename);
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
progressBar.reset();
progressBar.setPercentMode(true);
progressBar.setDescription("Extracting " + desc);
progressBar.setMaximum(zipFile.size());
FileUtil.ensureDirectoryExists(destFolder);
int count = 0;
int failedCount = 0;
while (entries.hasMoreElements()) {
if (cancel) { break; }
try {
final ZipEntry entry = entries.nextElement();
final String path = destFolder + entry.getName();
if (entry.isDirectory()) {
new File(path).mkdir();
progressBar.setValue(++count);
continue;
}
copyInputStream(zipFile.getInputStream(entry), path);
progressBar.setValue(++count);
filesExtracted++;
}
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
progressBar.setValue(++count);
failedCount++;
}
}
if (failedCount > 0) {
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
}
zipFile.close();
new File(zipFilename).delete();
}
catch (final Exception e) {
e.printStackTrace();
}
finally {
GuiBase.getInterface().preventSystemSleep(false);
}
}
public String download(final String filename) {
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while downloading
progressBar.reset();
progressBar.setPercentMode(true);
progressBar.setDescription("Downloading " + desc);
try {
final URL url = new URL(sourceUrl);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection(getProxy());
if (url.getPath().endsWith(".php")) {
//ensure file can be downloaded if returned from PHP script
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
}
conn.connect();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
final long contentLength = conn.getContentLength();
if (contentLength == 0) {
return null;
}
progressBar.setMaximum(100);
// input stream to read file - with 8k buffer
final InputStream input = new BufferedInputStream(conn.getInputStream(), 8192);
FileUtil.ensureDirectoryExists(destFolder);
// output stream to write file
final String destFile = destFolder + filename;
final OutputStream output = new FileOutputStream(destFile);
int count;
long total = 0;
final byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
if (cancel) { break; }
total += count;
progressBar.setValue((int)(100 * total / contentLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
if (cancel) {
new File(destFile).delete();
return null;
}
return destFile;
}
catch (final Exception ex) {
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
return null;
}
finally {
GuiBase.getInterface().preventSystemSleep(false);
}
}
protected void copyInputStream(final InputStream in, final String outPath) throws IOException{
final byte[] buffer = new byte[1024];
int len;
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outPath));
while((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
package forge.download;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.esotericsoftware.minlog.Log;
import com.google.common.io.Files;
import forge.FThreads;
import forge.GuiBase;
import forge.interfaces.IProgressBar;
import forge.util.FileUtil;
public class GuiDownloadZipService extends GuiDownloadService {
private final String name, desc, sourceUrl, destFolder, deleteFolder;
private int filesExtracted;
public GuiDownloadZipService(final String name0, final String desc0, final String sourceUrl0, final String destFolder0, final String deleteFolder0, final IProgressBar progressBar0) {
name = name0;
desc = desc0;
sourceUrl = sourceUrl0;
destFolder = destFolder0;
deleteFolder = deleteFolder0;
progressBar = progressBar0;
}
@Override
public String getTitle() {
return "Download " + name;
}
@Override
protected String getStartOverrideDesc() {
return desc;
}
@Override
protected final Map<String, String> getNeededFiles() {
final Map<String, String> files = new HashMap<String, String>();
files.put("_", "_");
return files; //not needed by zip service, so just return map of size 1
}
@Override
public final void run() {
downloadAndUnzip();
if (!cancel) {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
progressBar.setDescription(filesExtracted + " " + desc + " extracted");
finish();
}
});
}
}
public void downloadAndUnzip() {
filesExtracted = 0;
String zipFilename = download("temp.zip");
if (zipFilename == null) { return; }
//if assets.zip downloaded successfully, unzip into destination folder
try {
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
if (deleteFolder != null) {
final File deleteDir = new File(deleteFolder);
if (deleteDir.exists()) {
//attempt to delete previous res directory if to be rebuilt
progressBar.reset();
progressBar.setDescription("Deleting old " + desc + "...");
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
final String oldZipFilename = zipFilename;
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
Files.move(new File(oldZipFilename), new File(zipFilename));
}
FileUtil.deleteDirectory(deleteDir);
}
}
final ZipFile zipFile = new ZipFile(zipFilename);
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
progressBar.reset();
progressBar.setPercentMode(true);
progressBar.setDescription("Extracting " + desc);
progressBar.setMaximum(zipFile.size());
FileUtil.ensureDirectoryExists(destFolder);
int count = 0;
int failedCount = 0;
while (entries.hasMoreElements()) {
if (cancel) { break; }
try {
final ZipEntry entry = entries.nextElement();
final String path = destFolder + entry.getName();
if (entry.isDirectory()) {
new File(path).mkdir();
progressBar.setValue(++count);
continue;
}
copyInputStream(zipFile.getInputStream(entry), path);
progressBar.setValue(++count);
filesExtracted++;
}
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
progressBar.setValue(++count);
failedCount++;
}
}
if (failedCount > 0) {
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
}
zipFile.close();
new File(zipFilename).delete();
}
catch (final Exception e) {
e.printStackTrace();
}
finally {
GuiBase.getInterface().preventSystemSleep(false);
}
}
public String download(final String filename) {
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while downloading
progressBar.reset();
progressBar.setPercentMode(true);
progressBar.setDescription("Downloading " + desc);
try {
final URL url = new URL(sourceUrl);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection(getProxy());
if (url.getPath().endsWith(".php")) {
//ensure file can be downloaded if returned from PHP script
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
}
conn.connect();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
final long contentLength = conn.getContentLength();
if (contentLength == 0) {
return null;
}
progressBar.setMaximum(100);
// input stream to read file - with 8k buffer
final InputStream input = new BufferedInputStream(conn.getInputStream(), 8192);
FileUtil.ensureDirectoryExists(destFolder);
// output stream to write file
final String destFile = destFolder + filename;
final OutputStream output = new FileOutputStream(destFile);
int count;
long total = 0;
final byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
if (cancel) { break; }
total += count;
progressBar.setValue((int)(100 * total / contentLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
if (cancel) {
new File(destFile).delete();
return null;
}
return destFile;
}
catch (final Exception ex) {
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
return null;
}
finally {
GuiBase.getInterface().preventSystemSleep(false);
}
}
protected void copyInputStream(final InputStream in, final String outPath) throws IOException{
final byte[] buffer = new byte[1024];
int len;
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outPath));
while((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}

View File

@@ -1,195 +1,195 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.error;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import forge.FThreads;
import forge.GuiBase;
import forge.util.BuildInfo;
import forge.util.gui.SOptionPane;
/**
* The class ErrorViewer. Enables showing and saving error messages that
* occurred in forge.
*
* @author Clemens Koza
* @version V1.0 02.08.2009
*/
public class BugReporter {
private static final int STACK_OVERFLOW_MAX_MESSAGE_LEN = 16 * 1024;
public static final String REPORT = "Report";
public static final String SAVE = "Save";
public static final String CONTINUE = "Continue";
public static final String EXIT = "Exit";
public static final String HELP_TEXT = String.format(
"A template for a post in the bug reports forum topic is shown below. Just select '%s' "
+ "and the template will be copied to your system clipboard and the forum page will open in your browser. "
+ "Then all you have to do is paste the text into a forum post and edit the description line.", REPORT);
public static final String HELP_URL_LABEL =
"Reporting bugs in Forge is very important. We sincerely thank you for your time."
+ " For help writing a solid bug report, please see:";
public static final String HELP_URL =
"http://www.slightlymagic.net/forum/viewtopic.php?f=26&p=109925#p109925";
private static final String FORUM_URL;
static {
if (BuildInfo.isDevelopmentVersion()) {
FORUM_URL = "http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=54564487645#bottom";
} else {
FORUM_URL = "http://www.slightlymagic.net/forum/viewforum.php?f=26";
}
}
/**
* Shows exception information in a format ready to post to the forum as a
* crash report. Uses the exception's message as the reason if message is
* null.
*/
public static void reportException(final Throwable ex, final String message) {
if (ex == null) {
return;
}
if (message != null) {
System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(), message);
}
System.err.print(FThreads.debugGetCurrThreadId() + " > ");
ex.printStackTrace();
final StringBuilder sb = new StringBuilder();
sb.append("Description: [describe what you were doing when the crash occurred]\n\n");
buildSpoilerHeader(sb, ex.getClass().getSimpleName());
sb.append("\n\n");
if (null != message && !message.isEmpty()) {
sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n");
}
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
final String swStr = sw.toString();
if (ex instanceof StackOverflowError && swStr.length() >= STACK_OVERFLOW_MAX_MESSAGE_LEN) {
// most likely a cycle. only take first portion so the message
// doesn't grow too large to post
sb.append(swStr, 0, STACK_OVERFLOW_MAX_MESSAGE_LEN);
sb.append("\n... (truncated)");
}
else {
sb.append(swStr);
}
buildSpoilerFooter(sb);
GuiBase.getInterface().showBugReportDialog("Report a crash", sb.toString(), true);
}
/**
* Alias for reportException(ex, null).
*/
public static void reportException(final Throwable ex) {
reportException(ex, null);
}
/**
* Alias for reportException(ex, String.format(format, args)).
*/
public static void reportException(final Throwable ex, final String format, final Object... args) {
reportException(ex, String.format(format, args));
}
/**
* Shows a forum post template for reporting a bug.
*/
public static void reportBug(final String details) {
final StringBuilder sb = new StringBuilder();
sb.append("Description: [describe the problem]\n\n");
buildSpoilerHeader(sb, "General bug report");
if (null != details && !details.isEmpty()) {
sb.append("\n\n");
sb.append(details);
}
buildSpoilerFooter(sb);
GuiBase.getInterface().showBugReportDialog("Report a bug", sb.toString(), false);
}
private static StringBuilder buildSpoilerHeader(final StringBuilder sb, final String reportTitle) {
sb.append("[spoiler=").append(reportTitle).append("][code]");
sb.append("\nForge Version: ").append(GuiBase.getInterface().getCurrentVersion());
sb.append("\nOperating System: ").append(System.getProperty("os.name"))
.append(" ").append(System.getProperty("os.version"))
.append(" ").append(System.getProperty("os.arch"));
sb.append("\nJava Version: ").append(System.getProperty("java.version"))
.append(" ").append(System.getProperty("java.vendor"));
return sb;
}
private static StringBuilder buildSpoilerFooter(final StringBuilder sb) {
sb.append("[/code][/spoiler]");
return sb;
}
public static void copyAndGoToForums(final String text) {
try {
// copy text to clipboard
GuiBase.getInterface().copyToClipboard(text);
GuiBase.getInterface().browseToUrl(FORUM_URL);
} catch (final Exception ex) {
SOptionPane.showMessageDialog("Sorry, a problem occurred while opening the forum in your default browser.",
"A problem occurred", SOptionPane.ERROR_ICON);
}
}
public static void saveToFile(final String text) {
File f;
final long curTime = System.currentTimeMillis();
for (int i = 0;; i++) {
final String name = String.format("%TF-%02d.txt", curTime, i);
f = new File(name);
if (!f.exists()) {
break;
}
}
f = GuiBase.getInterface().getSaveFile(f);
try {
final BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write(text);
bw.close();
}
catch (final IOException ex) {
SOptionPane.showMessageDialog("There was an error during saving. Sorry!\n" + ex,
"Error saving file", SOptionPane.ERROR_ICON);
}
}
/**
* Private constructor to prevent instantiation.
*/
private BugReporter() {
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.error;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import forge.FThreads;
import forge.GuiBase;
import forge.util.BuildInfo;
import forge.util.gui.SOptionPane;
/**
* The class ErrorViewer. Enables showing and saving error messages that
* occurred in forge.
*
* @author Clemens Koza
* @version V1.0 02.08.2009
*/
public class BugReporter {
private static final int STACK_OVERFLOW_MAX_MESSAGE_LEN = 16 * 1024;
public static final String REPORT = "Report";
public static final String SAVE = "Save";
public static final String CONTINUE = "Continue";
public static final String EXIT = "Exit";
public static final String HELP_TEXT = String.format(
"A template for a post in the bug reports forum topic is shown below. Just select '%s' "
+ "and the template will be copied to your system clipboard and the forum page will open in your browser. "
+ "Then all you have to do is paste the text into a forum post and edit the description line.", REPORT);
public static final String HELP_URL_LABEL =
"Reporting bugs in Forge is very important. We sincerely thank you for your time."
+ " For help writing a solid bug report, please see:";
public static final String HELP_URL =
"http://www.slightlymagic.net/forum/viewtopic.php?f=26&p=109925#p109925";
private static final String FORUM_URL;
static {
if (BuildInfo.isDevelopmentVersion()) {
FORUM_URL = "http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=54564487645#bottom";
} else {
FORUM_URL = "http://www.slightlymagic.net/forum/viewforum.php?f=26";
}
}
/**
* Shows exception information in a format ready to post to the forum as a
* crash report. Uses the exception's message as the reason if message is
* null.
*/
public static void reportException(final Throwable ex, final String message) {
if (ex == null) {
return;
}
if (message != null) {
System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(), message);
}
System.err.print(FThreads.debugGetCurrThreadId() + " > ");
ex.printStackTrace();
final StringBuilder sb = new StringBuilder();
sb.append("Description: [describe what you were doing when the crash occurred]\n\n");
buildSpoilerHeader(sb, ex.getClass().getSimpleName());
sb.append("\n\n");
if (null != message && !message.isEmpty()) {
sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n");
}
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
final String swStr = sw.toString();
if (ex instanceof StackOverflowError && swStr.length() >= STACK_OVERFLOW_MAX_MESSAGE_LEN) {
// most likely a cycle. only take first portion so the message
// doesn't grow too large to post
sb.append(swStr, 0, STACK_OVERFLOW_MAX_MESSAGE_LEN);
sb.append("\n... (truncated)");
}
else {
sb.append(swStr);
}
buildSpoilerFooter(sb);
GuiBase.getInterface().showBugReportDialog("Report a crash", sb.toString(), true);
}
/**
* Alias for reportException(ex, null).
*/
public static void reportException(final Throwable ex) {
reportException(ex, null);
}
/**
* Alias for reportException(ex, String.format(format, args)).
*/
public static void reportException(final Throwable ex, final String format, final Object... args) {
reportException(ex, String.format(format, args));
}
/**
* Shows a forum post template for reporting a bug.
*/
public static void reportBug(final String details) {
final StringBuilder sb = new StringBuilder();
sb.append("Description: [describe the problem]\n\n");
buildSpoilerHeader(sb, "General bug report");
if (null != details && !details.isEmpty()) {
sb.append("\n\n");
sb.append(details);
}
buildSpoilerFooter(sb);
GuiBase.getInterface().showBugReportDialog("Report a bug", sb.toString(), false);
}
private static StringBuilder buildSpoilerHeader(final StringBuilder sb, final String reportTitle) {
sb.append("[spoiler=").append(reportTitle).append("][code]");
sb.append("\nForge Version: ").append(GuiBase.getInterface().getCurrentVersion());
sb.append("\nOperating System: ").append(System.getProperty("os.name"))
.append(" ").append(System.getProperty("os.version"))
.append(" ").append(System.getProperty("os.arch"));
sb.append("\nJava Version: ").append(System.getProperty("java.version"))
.append(" ").append(System.getProperty("java.vendor"));
return sb;
}
private static StringBuilder buildSpoilerFooter(final StringBuilder sb) {
sb.append("[/code][/spoiler]");
return sb;
}
public static void copyAndGoToForums(final String text) {
try {
// copy text to clipboard
GuiBase.getInterface().copyToClipboard(text);
GuiBase.getInterface().browseToUrl(FORUM_URL);
} catch (final Exception ex) {
SOptionPane.showMessageDialog("Sorry, a problem occurred while opening the forum in your default browser.",
"A problem occurred", SOptionPane.ERROR_ICON);
}
}
public static void saveToFile(final String text) {
File f;
final long curTime = System.currentTimeMillis();
for (int i = 0;; i++) {
final String name = String.format("%TF-%02d.txt", curTime, i);
f = new File(name);
if (!f.exists()) {
break;
}
}
f = GuiBase.getInterface().getSaveFile(f);
try {
final BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write(text);
bw.close();
}
catch (final IOException ex) {
SOptionPane.showMessageDialog("There was an error during saving. Sorry!\n" + ex,
"Error saving file", SOptionPane.ERROR_ICON);
}
}
/**
* Private constructor to prevent instantiation.
*/
private BugReporter() {
}
}

View File

@@ -1,7 +1,7 @@
package forge.events;
public interface IUiEventVisitor<T> {
T visit(UiEventBlockerAssigned event);
T visit(UiEventAttackerDeclared event);
T visit(UiEventNextGameDecision event);
package forge.events;
public interface IUiEventVisitor<T> {
T visit(UiEventBlockerAssigned event);
T visit(UiEventAttackerDeclared event);
T visit(UiEventNextGameDecision event);
}

View File

@@ -1,8 +1,8 @@
package forge.events;
import forge.game.event.Event;
public abstract class UiEvent extends Event {
public abstract <T> T visit(IUiEventVisitor<T> visitor);
package forge.events;
import forge.game.event.Event;
public abstract class UiEvent extends Event {
public abstract <T> T visit(IUiEventVisitor<T> visitor);
}

View File

@@ -1,27 +1,27 @@
package forge.events;
import forge.game.GameEntityView;
import forge.game.card.CardView;
public class UiEventAttackerDeclared extends UiEvent {
public final CardView attacker;
public final GameEntityView defender;
public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) {
attacker = card;
defender = currentDefender;
}
@Override
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender );
}
}
package forge.events;
import forge.game.GameEntityView;
import forge.game.card.CardView;
public class UiEventAttackerDeclared extends UiEvent {
public final CardView attacker;
public final GameEntityView defender;
public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) {
attacker = card;
defender = currentDefender;
}
@Override
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender );
}
}

View File

@@ -1,18 +1,18 @@
package forge.events;
import forge.game.card.CardView;
public class UiEventBlockerAssigned extends UiEvent {
public final CardView blocker;
public final CardView attackerBeingBlocked;
public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) {
blocker = card;
attackerBeingBlocked = currentAttacker;
}
@Override
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
package forge.events;
import forge.game.card.CardView;
public class UiEventBlockerAssigned extends UiEvent {
public final CardView blocker;
public final CardView attackerBeingBlocked;
public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) {
blocker = card;
attackerBeingBlocked = currentAttacker;
}
@Override
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -1,155 +1,155 @@
package forge.gauntlet;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import forge.GuiBase;
import forge.deck.Deck;
import forge.game.GameType;
import forge.game.player.RegisteredPlayer;
import forge.match.HostedMatch;
import forge.properties.ForgeConstants;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Handles layout saving and loading.
*
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
*/
public final class GauntletData {
@XStreamOmitField
private String name; // set based on the the filename on load
private transient HostedMatch hostedMatch = null;
private int completed;
private String timestamp;
private List<String> eventRecords = new ArrayList<String>();
private List<String> eventNames = new ArrayList<String>();
private Deck userDeck;
private List<Deck> decks;
public GauntletData() {
}
public void setName(String name0) {
name = name0;
}
public void rename(final String newName) {
File newpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, newName + ".dat");
File oldpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + ".dat");
oldpath.renameTo(newpath);
name = newName;
GauntletIO.saveGauntlet(this);
}
public String getName() {
return name;
}
public String getDisplayName() {
if (name.startsWith(GauntletIO.PREFIX_LOCKED)) { //trim locked prefix if needed
return name.substring(GauntletIO.PREFIX_LOCKED.length());
}
return name;
}
public void stamp() {
final DateFormat dateFormat = new SimpleDateFormat("MM-dd-yy, H:m");
timestamp = dateFormat.format(new Date()).toString();
}
/** Resets a gauntlet data to an unplayed state, then stamps and saves. */
public void reset() {
completed = 0;
stamp();
eventRecords.clear();
for (int i = 0; i < decks.size(); i++) {
eventRecords.add("");
}
GauntletIO.saveGauntlet(this);
}
public String getTimestamp() {
return timestamp;
}
public void setCompleted(final int i0) {
completed = i0;
}
public int getCompleted() {
return completed;
}
public void setUserDeck(final Deck d0) {
userDeck = d0;
}
public Deck getUserDeck() {
return userDeck;
}
public List<String> getDeckNames() {
final List<String> names = new ArrayList<String>();
for (final Deck d : decks) { names.add(d.getName()); }
return names;
}
public void setEventRecords(final List<String> records0) {
eventRecords = records0;
}
public List<String> getEventRecords() {
return eventRecords;
}
public void setEventNames(final List<String> names0) {
eventNames = names0;
}
public List<String> getEventNames() {
return eventNames;
}
public void setDecks(final List<Deck> decks0) {
decks = decks0;
}
public List<Deck> getDecks() {
return decks;
}
public void startRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
hostedMatch = GuiBase.getInterface().hostMatch();
hostedMatch.startMatch(GameType.Gauntlet, null, players, human, GuiBase.getInterface().getNewGuiGame());
}
public void nextRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
if (hostedMatch == null) {
throw new IllegalStateException("Cannot advance round when no match has been hosted.");
}
hostedMatch.endCurrentGame();
startRound(players, human);
}
@Override
public String toString() {
String str = getDisplayName();
if (decks != null) {
str += " (" + decks.size() + " opponents)";
}
return str;
}
}
package forge.gauntlet;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import forge.GuiBase;
import forge.deck.Deck;
import forge.game.GameType;
import forge.game.player.RegisteredPlayer;
import forge.match.HostedMatch;
import forge.properties.ForgeConstants;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Handles layout saving and loading.
*
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
*/
public final class GauntletData {
@XStreamOmitField
private String name; // set based on the the filename on load
private transient HostedMatch hostedMatch = null;
private int completed;
private String timestamp;
private List<String> eventRecords = new ArrayList<String>();
private List<String> eventNames = new ArrayList<String>();
private Deck userDeck;
private List<Deck> decks;
public GauntletData() {
}
public void setName(String name0) {
name = name0;
}
public void rename(final String newName) {
File newpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, newName + ".dat");
File oldpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + ".dat");
oldpath.renameTo(newpath);
name = newName;
GauntletIO.saveGauntlet(this);
}
public String getName() {
return name;
}
public String getDisplayName() {
if (name.startsWith(GauntletIO.PREFIX_LOCKED)) { //trim locked prefix if needed
return name.substring(GauntletIO.PREFIX_LOCKED.length());
}
return name;
}
public void stamp() {
final DateFormat dateFormat = new SimpleDateFormat("MM-dd-yy, H:m");
timestamp = dateFormat.format(new Date()).toString();
}
/** Resets a gauntlet data to an unplayed state, then stamps and saves. */
public void reset() {
completed = 0;
stamp();
eventRecords.clear();
for (int i = 0; i < decks.size(); i++) {
eventRecords.add("");
}
GauntletIO.saveGauntlet(this);
}
public String getTimestamp() {
return timestamp;
}
public void setCompleted(final int i0) {
completed = i0;
}
public int getCompleted() {
return completed;
}
public void setUserDeck(final Deck d0) {
userDeck = d0;
}
public Deck getUserDeck() {
return userDeck;
}
public List<String> getDeckNames() {
final List<String> names = new ArrayList<String>();
for (final Deck d : decks) { names.add(d.getName()); }
return names;
}
public void setEventRecords(final List<String> records0) {
eventRecords = records0;
}
public List<String> getEventRecords() {
return eventRecords;
}
public void setEventNames(final List<String> names0) {
eventNames = names0;
}
public List<String> getEventNames() {
return eventNames;
}
public void setDecks(final List<Deck> decks0) {
decks = decks0;
}
public List<Deck> getDecks() {
return decks;
}
public void startRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
hostedMatch = GuiBase.getInterface().hostMatch();
hostedMatch.startMatch(GameType.Gauntlet, null, players, human, GuiBase.getInterface().getNewGuiGame());
}
public void nextRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
if (hostedMatch == null) {
throw new IllegalStateException("Cannot advance round when no match has been hosted.");
}
hostedMatch.endCurrentGame();
startRound(players, human);
}
@Override
public String toString() {
String str = getDisplayName();
if (decks != null) {
str += " (" + decks.size() + " opponents)";
}
return str;
}
}

View File

@@ -1,195 +1,195 @@
package forge.gauntlet;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.lang3.StringUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import forge.deck.CardPool;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.IgnoringXStream;
public class GauntletIO {
/** Prompt in text field for new (unsaved) built gauntlets. */
public static final String TXF_PROMPT = "[New Gauntlet]";
/** suffix for all gauntlet data files */
public static final String SUFFIX_DATA = ".dat";
/** Prefix for quick gauntlet save files. */
public static final String PREFIX_QUICK = "Quick_";
/** Prefix for custom gauntlet save files. */
public static final String PREFIX_CUSTOM = "Custom_";
/** Regex for locked gauntlet save files. */
public static final String PREFIX_LOCKED = "LOCKED_";
protected static XStream getSerializer(final boolean isIgnoring) {
final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream();
xStream.registerConverter(new DeckSectionToXml());
xStream.autodetectAnnotations(true);
return xStream;
}
public static File getGauntletFile(final String name) {
return new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + SUFFIX_DATA);
}
public static File getGauntletFile(final GauntletData gd) {
return getGauntletFile(gd.getName());
}
public static File[] getGauntletFilesUnlocked(final String prefix) {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return ((prefix == null || name.startsWith(prefix)) && name.endsWith(SUFFIX_DATA));
}
};
final File folder = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc);
return folder.listFiles(filter);
}
public static File[] getGauntletFilesLocked() {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return (name.startsWith(PREFIX_LOCKED) && name.endsWith(SUFFIX_DATA));
}
};
final File folder = new File(ForgeConstants.GAUNTLET_DIR.defaultLoc);
return folder.listFiles(filter);
}
public static GauntletData loadGauntlet(final File xmlSaveFile) {
GZIPInputStream zin = null;
boolean isCorrupt = false;
try {
zin = new GZIPInputStream(new FileInputStream(xmlSaveFile));
final InputStreamReader reader = new InputStreamReader(zin);
final GauntletData data = (GauntletData)GauntletIO.getSerializer(true).fromXML(reader);
final String filename = xmlSaveFile.getName();
data.setName(filename.substring(0, filename.length() - SUFFIX_DATA.length()));
return data;
}
catch (final IOException e) {
e.printStackTrace();
}
catch (final Exception e) { //if there's a non-IO exception, delete the corrupt file
e.printStackTrace();
isCorrupt = true;
}
finally {
if (zin != null) {
try {
zin.close();
} catch (final IOException e) {
System.out.println("error closing gauntlet data reader: " + e);
}
}
}
if (isCorrupt) {
try {
xmlSaveFile.delete();
} catch (final Exception e) {
System.out.println("error delete corrupt gauntlet file: " + e);
}
}
return null;
}
public static void saveGauntlet(final GauntletData gd0) {
try {
final XStream xStream = GauntletIO.getSerializer(false);
GauntletIO.savePacked(xStream, gd0);
} catch (final Exception ex) {
throw new RuntimeException(ex);
}
}
private static void savePacked(final XStream xStream0, final GauntletData gd0) throws IOException {
final BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(getGauntletFile(gd0)));
final GZIPOutputStream zout = new GZIPOutputStream(bout);
xStream0.toXML(gd0, zout);
zout.flush();
zout.close();
}
private static class DeckSectionToXml implements Converter {
@SuppressWarnings("rawtypes")
@Override
public boolean canConvert(final Class clasz) {
return clasz.equals(CardPool.class);
}
@Override
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
for (final Entry<PaperCard, Integer> e : (CardPool) source) {
writeCardPrinted(e.getKey(), e.getValue(), writer);
}
}
@Override
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
final CardPool result = new CardPool();
while (reader.hasMoreChildren()) {
reader.moveDown();
final String sCnt = reader.getAttribute("n");
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
final String nodename = reader.getNodeName();
if ("string".equals(nodename)) {
result.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
} else if ("card".equals(nodename)) { // new format
result.add(readCardPrinted(reader), cnt);
}
reader.moveUp();
}
return result;
}
private static void writeCardPrinted(final PaperCard cref, final Integer count, final HierarchicalStreamWriter writer) {
writer.startNode("card");
writer.addAttribute("c", cref.getName());
writer.addAttribute("s", cref.getEdition());
if (cref.isFoil()) {
writer.addAttribute("foil", "1");
}
writer.addAttribute("i", Integer.toString(cref.getArtIndex()));
writer.addAttribute("n", count.toString());
writer.endNode();
}
private static PaperCard readCardPrinted(final HierarchicalStreamReader reader) {
final String name = reader.getAttribute("c");
final String set = reader.getAttribute("s");
final String sIndex = reader.getAttribute("i");
final short index = StringUtils.isNumeric(sIndex) ? Short.parseShort(sIndex) : 0;
final boolean foil = "1".equals(reader.getAttribute("foil"));
PaperCard card = FModel.getMagicDb().getOrLoadCommonCard(name, set, index, foil);
if (null == card) {
throw new RuntimeException("Unsupported card found in quest save: " + name + " from edition " + set);
}
return card;
}
}
}
package forge.gauntlet;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.lang3.StringUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import forge.deck.CardPool;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.IgnoringXStream;
public class GauntletIO {
/** Prompt in text field for new (unsaved) built gauntlets. */
public static final String TXF_PROMPT = "[New Gauntlet]";
/** suffix for all gauntlet data files */
public static final String SUFFIX_DATA = ".dat";
/** Prefix for quick gauntlet save files. */
public static final String PREFIX_QUICK = "Quick_";
/** Prefix for custom gauntlet save files. */
public static final String PREFIX_CUSTOM = "Custom_";
/** Regex for locked gauntlet save files. */
public static final String PREFIX_LOCKED = "LOCKED_";
protected static XStream getSerializer(final boolean isIgnoring) {
final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream();
xStream.registerConverter(new DeckSectionToXml());
xStream.autodetectAnnotations(true);
return xStream;
}
public static File getGauntletFile(final String name) {
return new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + SUFFIX_DATA);
}
public static File getGauntletFile(final GauntletData gd) {
return getGauntletFile(gd.getName());
}
public static File[] getGauntletFilesUnlocked(final String prefix) {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return ((prefix == null || name.startsWith(prefix)) && name.endsWith(SUFFIX_DATA));
}
};
final File folder = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc);
return folder.listFiles(filter);
}
public static File[] getGauntletFilesLocked() {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return (name.startsWith(PREFIX_LOCKED) && name.endsWith(SUFFIX_DATA));
}
};
final File folder = new File(ForgeConstants.GAUNTLET_DIR.defaultLoc);
return folder.listFiles(filter);
}
public static GauntletData loadGauntlet(final File xmlSaveFile) {
GZIPInputStream zin = null;
boolean isCorrupt = false;
try {
zin = new GZIPInputStream(new FileInputStream(xmlSaveFile));
final InputStreamReader reader = new InputStreamReader(zin);
final GauntletData data = (GauntletData)GauntletIO.getSerializer(true).fromXML(reader);
final String filename = xmlSaveFile.getName();
data.setName(filename.substring(0, filename.length() - SUFFIX_DATA.length()));
return data;
}
catch (final IOException e) {
e.printStackTrace();
}
catch (final Exception e) { //if there's a non-IO exception, delete the corrupt file
e.printStackTrace();
isCorrupt = true;
}
finally {
if (zin != null) {
try {
zin.close();
} catch (final IOException e) {
System.out.println("error closing gauntlet data reader: " + e);
}
}
}
if (isCorrupt) {
try {
xmlSaveFile.delete();
} catch (final Exception e) {
System.out.println("error delete corrupt gauntlet file: " + e);
}
}
return null;
}
public static void saveGauntlet(final GauntletData gd0) {
try {
final XStream xStream = GauntletIO.getSerializer(false);
GauntletIO.savePacked(xStream, gd0);
} catch (final Exception ex) {
throw new RuntimeException(ex);
}
}
private static void savePacked(final XStream xStream0, final GauntletData gd0) throws IOException {
final BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(getGauntletFile(gd0)));
final GZIPOutputStream zout = new GZIPOutputStream(bout);
xStream0.toXML(gd0, zout);
zout.flush();
zout.close();
}
private static class DeckSectionToXml implements Converter {
@SuppressWarnings("rawtypes")
@Override
public boolean canConvert(final Class clasz) {
return clasz.equals(CardPool.class);
}
@Override
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
for (final Entry<PaperCard, Integer> e : (CardPool) source) {
writeCardPrinted(e.getKey(), e.getValue(), writer);
}
}
@Override
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
final CardPool result = new CardPool();
while (reader.hasMoreChildren()) {
reader.moveDown();
final String sCnt = reader.getAttribute("n");
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
final String nodename = reader.getNodeName();
if ("string".equals(nodename)) {
result.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
} else if ("card".equals(nodename)) { // new format
result.add(readCardPrinted(reader), cnt);
}
reader.moveUp();
}
return result;
}
private static void writeCardPrinted(final PaperCard cref, final Integer count, final HierarchicalStreamWriter writer) {
writer.startNode("card");
writer.addAttribute("c", cref.getName());
writer.addAttribute("s", cref.getEdition());
if (cref.isFoil()) {
writer.addAttribute("foil", "1");
}
writer.addAttribute("i", Integer.toString(cref.getArtIndex()));
writer.addAttribute("n", count.toString());
writer.endNode();
}
private static PaperCard readCardPrinted(final HierarchicalStreamReader reader) {
final String name = reader.getAttribute("c");
final String set = reader.getAttribute("s");
final String sIndex = reader.getAttribute("i");
final short index = StringUtils.isNumeric(sIndex) ? Short.parseShort(sIndex) : 0;
final boolean foil = "1".equals(reader.getAttribute("foil"));
PaperCard card = FModel.getMagicDb().getOrLoadCommonCard(name, set, index, foil);
if (null == card) {
throw new RuntimeException("Unsupported card found in quest save: " + name + " from edition " + set);
}
return card;
}
}
}

View File

@@ -1,88 +1,88 @@
package forge.gauntlet;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import forge.deck.Deck;
import forge.deck.DeckType;
import forge.deck.DeckgenUtil;
import forge.model.FModel;
public class GauntletUtil {
public static GauntletData createQuickGauntlet(final Deck userDeck, final int numOpponents, final List<DeckType> allowedDeckTypes) {
GauntletData gauntlet = new GauntletData();
setDefaultGauntletName(gauntlet, GauntletIO.PREFIX_QUICK);
FModel.setGauntletData(gauntlet);
// Generate gauntlet decks
Deck deck;
final List<String> eventNames = new ArrayList<String>();
final List<Deck> decks = new ArrayList<Deck>();
for (int i = 0; i < numOpponents; i++) {
int randType = (int)Math.floor(Math.random() * allowedDeckTypes.size());
switch (allowedDeckTypes.get(randType)) {
case COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(true);
eventNames.add("Random colors deck");
break;
case STANDARD_COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true);
break;
case STANDARD_CARDGEN_DECK:
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),true);
break;
case MODERN_CARDGEN_DECK:
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),true);
break;
case MODERN_COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true);
break;
case CUSTOM_DECK:
deck = DeckgenUtil.getRandomCustomDeck();
eventNames.add(deck.getName());
break;
case PRECONSTRUCTED_DECK:
deck = DeckgenUtil.getRandomPreconDeck();
eventNames.add(deck.getName());
break;
case QUEST_OPPONENT_DECK:
deck = DeckgenUtil.getRandomQuestDeck();
eventNames.add(deck.getName());
break;
case THEME_DECK:
deck = DeckgenUtil.getRandomThemeDeck();
eventNames.add(deck.getName());
break;
default:
continue;
}
decks.add(deck);
}
gauntlet.setDecks(decks);
gauntlet.setEventNames(eventNames);
gauntlet.setUserDeck(userDeck);
// Reset all variable fields to 0, stamps and saves automatically.
gauntlet.reset();
return gauntlet;
}
public static void setDefaultGauntletName(GauntletData gauntlet, String prefix) {
final File[] arrFiles = GauntletIO.getGauntletFilesUnlocked(prefix);
final Set<String> setNames = new HashSet<String>();
for (File f : arrFiles) {
setNames.add(f.getName());
}
int num = 1;
while (setNames.contains(prefix + num + GauntletIO.SUFFIX_DATA)) {
num++;
}
gauntlet.setName(prefix + num);
}
}
package forge.gauntlet;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import forge.deck.Deck;
import forge.deck.DeckType;
import forge.deck.DeckgenUtil;
import forge.model.FModel;
public class GauntletUtil {
public static GauntletData createQuickGauntlet(final Deck userDeck, final int numOpponents, final List<DeckType> allowedDeckTypes) {
GauntletData gauntlet = new GauntletData();
setDefaultGauntletName(gauntlet, GauntletIO.PREFIX_QUICK);
FModel.setGauntletData(gauntlet);
// Generate gauntlet decks
Deck deck;
final List<String> eventNames = new ArrayList<String>();
final List<Deck> decks = new ArrayList<Deck>();
for (int i = 0; i < numOpponents; i++) {
int randType = (int)Math.floor(Math.random() * allowedDeckTypes.size());
switch (allowedDeckTypes.get(randType)) {
case COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(true);
eventNames.add("Random colors deck");
break;
case STANDARD_COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true);
break;
case STANDARD_CARDGEN_DECK:
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),true);
break;
case MODERN_CARDGEN_DECK:
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),true);
break;
case MODERN_COLOR_DECK:
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true);
break;
case CUSTOM_DECK:
deck = DeckgenUtil.getRandomCustomDeck();
eventNames.add(deck.getName());
break;
case PRECONSTRUCTED_DECK:
deck = DeckgenUtil.getRandomPreconDeck();
eventNames.add(deck.getName());
break;
case QUEST_OPPONENT_DECK:
deck = DeckgenUtil.getRandomQuestDeck();
eventNames.add(deck.getName());
break;
case THEME_DECK:
deck = DeckgenUtil.getRandomThemeDeck();
eventNames.add(deck.getName());
break;
default:
continue;
}
decks.add(deck);
}
gauntlet.setDecks(decks);
gauntlet.setEventNames(eventNames);
gauntlet.setUserDeck(userDeck);
// Reset all variable fields to 0, stamps and saves automatically.
gauntlet.reset();
return gauntlet;
}
public static void setDefaultGauntletName(GauntletData gauntlet, String prefix) {
final File[] arrFiles = GauntletIO.getGauntletFilesUnlocked(prefix);
final Set<String> setNames = new HashSet<String>();
for (File f : arrFiles) {
setNames.add(f.getName());
}
int num = 1;
while (setNames.contains(prefix + num + GauntletIO.SUFFIX_DATA)) {
num++;
}
gauntlet.setName(prefix + num);
}
}

View File

@@ -1,141 +1,141 @@
package forge.gauntlet;
import java.util.List;
import com.google.common.collect.Lists;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.Deck;
import forge.game.GameView;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
public abstract class GauntletWinLoseController {
private static final String SAVE_AND_QUIT = "Save and Quit";
private final IWinLoseView<? extends IButton> view;
private final GameView lastGame;
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
view = view0;
lastGame = game0;
}
public void showOutcome() {
final GauntletData gd = FModel.getGauntletData();
final List<String> lstEventNames = gd.getEventNames();
final List<Deck> lstDecks = gd.getDecks();
final List<String> lstEventRecords = gd.getEventRecords();
final int len = lstEventNames.size();
final int num = gd.getCompleted();
FSkinProp icon = null;
String message1 = null;
String message2 = null;
// No restarts.
view.getBtnRestart().setVisible(false);
// Generic event record.
lstEventRecords.set(gd.getCompleted(), "Ongoing");
// Match won't be saved until it is over. This opens up a cheat
// or failsafe mechanism (depending on your perspective) in which
// the player can restart Forge to replay a match.
// Pretty sure this can't be fixed until in-game states can be
// saved. Doublestrike 07-10-12
LobbyPlayer questPlayer = GamePlayerUtil.getGuiPlayer();
// In all cases, update stats.
lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - "
+ (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer) + 1));
boolean isMatchOver = lastGame.isMatchOver();
if (isMatchOver) {
gd.setCompleted(gd.getCompleted() + 1);
// Win match case
if (lastGame.isMatchWonBy(questPlayer)) {
// Gauntlet complete: Remove save file
if (gd.getCompleted() == lstDecks.size()) {
icon = FSkinProp.ICO_QUEST_COIN;
message1 = "CONGRATULATIONS!";
message2 = "You made it through the gauntlet!";
view.getBtnContinue().setVisible(false);
view.getBtnQuit().setText("OK");
// Remove save file if it's a quickie, or just reset it.
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
GauntletIO.getGauntletFile(gd).delete();
}
else {
gd.reset();
}
}
// Or, save and move to next game
else {
gd.stamp();
GauntletIO.saveGauntlet(gd);
view.getBtnContinue().setText("Next Round (" + (gd.getCompleted() + 1)
+ "/" + len + ")");
view.getBtnContinue().setVisible(true);
view.getBtnContinue().setEnabled(true);
view.getBtnQuit().setText("Save and Quit");
}
}
// Lose match case; stop gauntlet.
else {
icon = FSkinProp.ICO_QUEST_HEART;
message1 = "DEFEATED!";
message2 = "You have failed to pass the gauntlet.";
view.getBtnContinue().setVisible(false);
// Remove save file if it's a quickie, or just reset it.
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
GauntletIO.getGauntletFile(gd).delete();
}
else {
gd.reset();
}
}
}
gd.setEventRecords(lstEventRecords);
showOutcome(isMatchOver, message1, message2, icon, lstEventNames, lstEventRecords, len, num);
}
public final boolean actionOnContinue() {
if (lastGame.isMatchOver()) {
// To change the AI deck, we have to create a new match.
final GauntletData gd = FModel.getGauntletData();
final RegisteredPlayer human = new RegisteredPlayer(gd.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
final Deck aiDeck = gd.getDecks().get(gd.getCompleted());
final List<RegisteredPlayer> players = Lists.newArrayList();
players.add(human);
players.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
view.hide();
saveOptions();
gd.nextRound(players, human);
return true;
}
return false;
}
public final void actionOnQuit() {
if (!SAVE_AND_QUIT.equals(view.getBtnQuit().getText())) {
// Quitting mid-match abandons the gauntlet.
FModel.getGauntletData().reset();
}
}
protected abstract void showOutcome(boolean isMatchOver, String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num);
protected abstract void saveOptions();
}
package forge.gauntlet;
import java.util.List;
import com.google.common.collect.Lists;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.Deck;
import forge.game.GameView;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
public abstract class GauntletWinLoseController {
private static final String SAVE_AND_QUIT = "Save and Quit";
private final IWinLoseView<? extends IButton> view;
private final GameView lastGame;
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
view = view0;
lastGame = game0;
}
public void showOutcome() {
final GauntletData gd = FModel.getGauntletData();
final List<String> lstEventNames = gd.getEventNames();
final List<Deck> lstDecks = gd.getDecks();
final List<String> lstEventRecords = gd.getEventRecords();
final int len = lstEventNames.size();
final int num = gd.getCompleted();
FSkinProp icon = null;
String message1 = null;
String message2 = null;
// No restarts.
view.getBtnRestart().setVisible(false);
// Generic event record.
lstEventRecords.set(gd.getCompleted(), "Ongoing");
// Match won't be saved until it is over. This opens up a cheat
// or failsafe mechanism (depending on your perspective) in which
// the player can restart Forge to replay a match.
// Pretty sure this can't be fixed until in-game states can be
// saved. Doublestrike 07-10-12
LobbyPlayer questPlayer = GamePlayerUtil.getGuiPlayer();
// In all cases, update stats.
lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - "
+ (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer) + 1));
boolean isMatchOver = lastGame.isMatchOver();
if (isMatchOver) {
gd.setCompleted(gd.getCompleted() + 1);
// Win match case
if (lastGame.isMatchWonBy(questPlayer)) {
// Gauntlet complete: Remove save file
if (gd.getCompleted() == lstDecks.size()) {
icon = FSkinProp.ICO_QUEST_COIN;
message1 = "CONGRATULATIONS!";
message2 = "You made it through the gauntlet!";
view.getBtnContinue().setVisible(false);
view.getBtnQuit().setText("OK");
// Remove save file if it's a quickie, or just reset it.
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
GauntletIO.getGauntletFile(gd).delete();
}
else {
gd.reset();
}
}
// Or, save and move to next game
else {
gd.stamp();
GauntletIO.saveGauntlet(gd);
view.getBtnContinue().setText("Next Round (" + (gd.getCompleted() + 1)
+ "/" + len + ")");
view.getBtnContinue().setVisible(true);
view.getBtnContinue().setEnabled(true);
view.getBtnQuit().setText("Save and Quit");
}
}
// Lose match case; stop gauntlet.
else {
icon = FSkinProp.ICO_QUEST_HEART;
message1 = "DEFEATED!";
message2 = "You have failed to pass the gauntlet.";
view.getBtnContinue().setVisible(false);
// Remove save file if it's a quickie, or just reset it.
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
GauntletIO.getGauntletFile(gd).delete();
}
else {
gd.reset();
}
}
}
gd.setEventRecords(lstEventRecords);
showOutcome(isMatchOver, message1, message2, icon, lstEventNames, lstEventRecords, len, num);
}
public final boolean actionOnContinue() {
if (lastGame.isMatchOver()) {
// To change the AI deck, we have to create a new match.
final GauntletData gd = FModel.getGauntletData();
final RegisteredPlayer human = new RegisteredPlayer(gd.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
final Deck aiDeck = gd.getDecks().get(gd.getCompleted());
final List<RegisteredPlayer> players = Lists.newArrayList();
players.add(human);
players.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
view.hide();
saveOptions();
gd.nextRound(players, human);
return true;
}
return false;
}
public final void actionOnQuit() {
if (!SAVE_AND_QUIT.equals(view.getBtnQuit().getText())) {
// Quitting mid-match abandons the gauntlet.
FModel.getGauntletData().reset();
}
}
protected abstract void showOutcome(boolean isMatchOver, String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num);
protected abstract void saveOptions();
}

View File

@@ -1,13 +1,13 @@
package forge.interfaces;
import forge.UiCommand;
import forge.assets.FSkinProp;
public interface IButton extends ITextComponent {
boolean isSelected();
void setSelected(boolean b0);
boolean requestFocusInWindow();
void setCommand(UiCommand command0);
void setImage(FSkinProp color);
void setTextColor(int r, int g, int b);
}
package forge.interfaces;
import forge.UiCommand;
import forge.assets.FSkinProp;
public interface IButton extends ITextComponent {
boolean isSelected();
void setSelected(boolean b0);
boolean requestFocusInWindow();
void setCommand(UiCommand command0);
void setImage(FSkinProp color);
void setTextColor(int r, int g, int b);
}

View File

@@ -1,6 +1,6 @@
package forge.interfaces;
public interface ICheckBox extends IComponent {
boolean isSelected();
void setSelected(boolean b0);
}
package forge.interfaces;
public interface ICheckBox extends IComponent {
boolean isSelected();
void setSelected(boolean b0);
}

View File

@@ -1,10 +1,10 @@
package forge.interfaces;
public interface IComboBox<E> extends IComponent {
void setSelectedItem(E item);
void setSelectedIndex(int index);
void addItem(E item);
void removeAllItems();
int getSelectedIndex();
E getSelectedItem();
}
package forge.interfaces;
public interface IComboBox<E> extends IComponent {
void setSelectedItem(E item);
void setSelectedIndex(int index);
void addItem(E item);
void removeAllItems();
int getSelectedIndex();
E getSelectedItem();
}

View File

@@ -1,13 +1,13 @@
package forge.interfaces;
public interface IDeviceAdapter {
boolean isConnectedToInternet();
boolean isConnectedToWifi();
boolean isTablet();
String getDownloadsDir();
boolean openFile(String filename);
void setLandscapeMode(boolean landscapeMode);
void preventSystemSleep(boolean preventSleep);
void restart();
void exit();
}
package forge.interfaces;
public interface IDeviceAdapter {
boolean isConnectedToInternet();
boolean isConnectedToWifi();
boolean isTablet();
String getDownloadsDir();
boolean openFile(String filename);
void setLandscapeMode(boolean landscapeMode);
void preventSystemSleep(boolean preventSleep);
void restart();
void exit();
}

View File

@@ -1,59 +1,59 @@
package forge.interfaces;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Function;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.download.GuiDownloadService;
import forge.item.PaperCard;
import forge.match.HostedMatch;
import forge.sound.IAudioClip;
import forge.sound.IAudioMusic;
import forge.util.Callback;
public interface IGuiBase {
boolean isRunningOnDesktop();
boolean isLibgdxPort();
String getCurrentVersion();
String getAssetsDir();
void invokeInEdtNow(Runnable runnable);
void invokeInEdtLater(Runnable runnable);
void invokeInEdtAndWait(Runnable proc);
boolean isGuiThread();
ISkinImage getSkinIcon(FSkinProp skinProp);
ISkinImage getUnskinnedIcon(String path);
ISkinImage getCardArt(PaperCard card);
ISkinImage createLayeredImage(FSkinProp background, String overlayFilename, float opacity);
void showBugReportDialog(String title, String text, boolean showExitAppBtn);
void showImageDialog(ISkinImage image, String message, String title);
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, T selected, Function<T, String> display);
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
String showFileDialog(String title, String defaultDir);
File getSaveFile(File defaultFile);
void download(GuiDownloadService service, Callback<Boolean> callback);
void showCardList(String title, String message, List<PaperCard> list);
boolean showBoxedProduct(String title, String message, List<PaperCard> list);
PaperCard chooseCard(String title, String message, List<PaperCard> list);
int getAvatarCount();
void copyToClipboard(String text);
void browseToUrl(String url) throws IOException, URISyntaxException;
IAudioClip createAudioClip(String filename);
IAudioMusic createAudioMusic(String filename);
void startAltSoundSystem(String filename, boolean isSynchronized);
void clearImageCache();
void showSpellShop();
void showBazaar();
IGuiGame getNewGuiGame();
HostedMatch hostMatch();
void runBackgroundTask(String message, Runnable task);
String encodeSymbols(String str, boolean formatReminderText);
void preventSystemSleep(boolean preventSleep);
package forge.interfaces;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Function;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.download.GuiDownloadService;
import forge.item.PaperCard;
import forge.match.HostedMatch;
import forge.sound.IAudioClip;
import forge.sound.IAudioMusic;
import forge.util.Callback;
public interface IGuiBase {
boolean isRunningOnDesktop();
boolean isLibgdxPort();
String getCurrentVersion();
String getAssetsDir();
void invokeInEdtNow(Runnable runnable);
void invokeInEdtLater(Runnable runnable);
void invokeInEdtAndWait(Runnable proc);
boolean isGuiThread();
ISkinImage getSkinIcon(FSkinProp skinProp);
ISkinImage getUnskinnedIcon(String path);
ISkinImage getCardArt(PaperCard card);
ISkinImage createLayeredImage(FSkinProp background, String overlayFilename, float opacity);
void showBugReportDialog(String title, String text, boolean showExitAppBtn);
void showImageDialog(ISkinImage image, String message, String title);
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, T selected, Function<T, String> display);
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
String showFileDialog(String title, String defaultDir);
File getSaveFile(File defaultFile);
void download(GuiDownloadService service, Callback<Boolean> callback);
void showCardList(String title, String message, List<PaperCard> list);
boolean showBoxedProduct(String title, String message, List<PaperCard> list);
PaperCard chooseCard(String title, String message, List<PaperCard> list);
int getAvatarCount();
void copyToClipboard(String text);
void browseToUrl(String url) throws IOException, URISyntaxException;
IAudioClip createAudioClip(String filename);
IAudioMusic createAudioMusic(String filename);
void startAltSoundSystem(String filename, boolean isSynchronized);
void clearImageCache();
void showSpellShop();
void showBazaar();
IGuiGame getNewGuiGame();
HostedMatch hostMatch();
void runBackgroundTask(String message, Runnable task);
String encodeSymbols(String str, boolean formatReminderText);
void preventSystemSleep(boolean preventSleep);
}

View File

@@ -1,169 +1,169 @@
package forge.interfaces;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.google.common.base.Function;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.CardPool;
import forge.game.GameEntityView;
import forge.game.GameView;
import forge.game.card.CardView;
import forge.game.phase.PhaseType;
import forge.game.player.DelayedReveal;
import forge.game.player.IHasIcon;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbilityView;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.player.PlayerZoneUpdate;
import forge.trackable.TrackableCollection;
import forge.util.ITriggerEvent;
public interface IGuiGame {
void setGameView(GameView gameView);
void setOriginalGameController(PlayerView view, IGameController gameController);
void setGameController(PlayerView player, IGameController gameController);
void setSpectator(IGameController spectator);
void openView(TrackableCollection<PlayerView> myPlayers);
void afterGameEnd();
void showCombat();
void showPromptMessage(PlayerView playerView, String message);
void showPromptMessage(PlayerView playerView, String message, CardView card);
void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk);
void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1);
void flashIncorrectAction();
void updatePhase();
void updateTurn(PlayerView player);
void updatePlayerControl();
void enableOverlay();
void disableOverlay();
void finishGame();
void showManaPool(PlayerView player);
void hideManaPool(PlayerView player);
void updateStack();
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateSingleCard(CardView card);
void updateCards(Iterable<CardView> cards);
void refreshCardDetails(Iterable<CardView> cards);
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
void updateLives(Iterable<PlayerView> livesUpdate);
void setPanelSelection(CardView hostCard);
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
void message(String message);
void message(String message, String title);
void showErrorDialog(String message);
void showErrorDialog(String message, String title);
boolean showConfirmDialog(String message, String title);
boolean showConfirmDialog(String message, String title, boolean defaultYes);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes);
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
String showInputDialog(String message, String title);
String showInputDialog(String message, String title, FSkinProp icon);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
boolean confirm(CardView c, String question);
boolean confirm(CardView c, String question, List<String> options);
boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options);
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
// Get Integer in range
Integer getInteger(String message, int min);
Integer getInteger(String message, int min, int max);
Integer getInteger(String message, int min, int max, boolean sortDesc);
Integer getInteger(String message, int min, int max, int cutoff);
/**
* Convenience for getChoices(message, 0, 1, choices).
*
* @param <T>
* is automatically inferred.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* @see #getChoices(String, int, int, Object...)
*/
<T> T oneOrNone(String message, List<T> choices);
/**
* <p>
* getChoice.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty.
*/
<T> T one(String message, List<T> choices);
<T> void reveal(String message, List<T> items);
<T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c);
<T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode);
/**
* Ask the user to insert an object into a list of other objects. The
* current implementation requires the user to cancel in order to get the
* new item to be the first item in the resulting list.
*
* @param title
* the dialog title.
* @param newItem
* the object to insert.
* @param oldItems
* the list of objects.
* @return A shallow copy of the list of objects, with newItem inserted.
*/
<T> List<T> insertInList(String title, T newItem, List<T> oldItems);
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional); void setCard(CardView card);
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor);
void setHighlighted(PlayerView pv, boolean b);
void setUsedToPay(CardView card, boolean value);
void awaitNextInput();
void cancelAwaitNextInput();
boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase);
void autoPassUntilEndOfTurn(PlayerView player);
boolean mayAutoPass(PlayerView player);
void autoPassCancel(PlayerView player);
void updateAutoPassPrompt();
boolean shouldAutoYield(String key);
void setShouldAutoYield(String key, boolean autoYield);
boolean shouldAlwaysAcceptTrigger(int trigger);
boolean shouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAcceptTrigger(int trigger);
void setShouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAskTrigger(int trigger);
void clearAutoYields();
void setCurrentPlayer(PlayerView player);
}
package forge.interfaces;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.google.common.base.Function;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.CardPool;
import forge.game.GameEntityView;
import forge.game.GameView;
import forge.game.card.CardView;
import forge.game.phase.PhaseType;
import forge.game.player.DelayedReveal;
import forge.game.player.IHasIcon;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbilityView;
import forge.game.zone.ZoneType;
import forge.item.PaperCard;
import forge.player.PlayerZoneUpdate;
import forge.trackable.TrackableCollection;
import forge.util.ITriggerEvent;
public interface IGuiGame {
void setGameView(GameView gameView);
void setOriginalGameController(PlayerView view, IGameController gameController);
void setGameController(PlayerView player, IGameController gameController);
void setSpectator(IGameController spectator);
void openView(TrackableCollection<PlayerView> myPlayers);
void afterGameEnd();
void showCombat();
void showPromptMessage(PlayerView playerView, String message);
void showPromptMessage(PlayerView playerView, String message, CardView card);
void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk);
void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1);
void flashIncorrectAction();
void updatePhase();
void updateTurn(PlayerView player);
void updatePlayerControl();
void enableOverlay();
void disableOverlay();
void finishGame();
void showManaPool(PlayerView player);
void hideManaPool(PlayerView player);
void updateStack();
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateSingleCard(CardView card);
void updateCards(Iterable<CardView> cards);
void refreshCardDetails(Iterable<CardView> cards);
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
void updateLives(Iterable<PlayerView> livesUpdate);
void setPanelSelection(CardView hostCard);
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
void message(String message);
void message(String message, String title);
void showErrorDialog(String message);
void showErrorDialog(String message, String title);
boolean showConfirmDialog(String message, String title);
boolean showConfirmDialog(String message, String title, boolean defaultYes);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes);
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
String showInputDialog(String message, String title);
String showInputDialog(String message, String title, FSkinProp icon);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
boolean confirm(CardView c, String question);
boolean confirm(CardView c, String question, List<String> options);
boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options);
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
// Get Integer in range
Integer getInteger(String message, int min);
Integer getInteger(String message, int min, int max);
Integer getInteger(String message, int min, int max, boolean sortDesc);
Integer getInteger(String message, int min, int max, int cutoff);
/**
* Convenience for getChoices(message, 0, 1, choices).
*
* @param <T>
* is automatically inferred.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* @see #getChoices(String, int, int, Object...)
*/
<T> T oneOrNone(String message, List<T> choices);
/**
* <p>
* getChoice.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty.
*/
<T> T one(String message, List<T> choices);
<T> void reveal(String message, List<T> items);
<T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c);
<T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode);
/**
* Ask the user to insert an object into a list of other objects. The
* current implementation requires the user to cancel in order to get the
* new item to be the first item in the resulting list.
*
* @param title
* the dialog title.
* @param newItem
* the object to insert.
* @param oldItems
* the list of objects.
* @return A shallow copy of the list of objects, with newItem inserted.
*/
<T> List<T> insertInList(String title, T newItem, List<T> oldItems);
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional); void setCard(CardView card);
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor);
void setHighlighted(PlayerView pv, boolean b);
void setUsedToPay(CardView card, boolean value);
void awaitNextInput();
void cancelAwaitNextInput();
boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase);
void autoPassUntilEndOfTurn(PlayerView player);
boolean mayAutoPass(PlayerView player);
void autoPassCancel(PlayerView player);
void updateAutoPassPrompt();
boolean shouldAutoYield(String key);
void setShouldAutoYield(String key, boolean autoYield);
boolean shouldAlwaysAcceptTrigger(int trigger);
boolean shouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAcceptTrigger(int trigger);
void setShouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAskTrigger(int trigger);
void clearAutoYields();
void setCurrentPlayer(PlayerView player);
}

View File

@@ -1,5 +1,5 @@
package forge.interfaces;
public interface ILobbyView extends IUpdateable {
void setPlayerChangeListener(IPlayerChangeListener iPlayerChangeListener);
}
package forge.interfaces;
public interface ILobbyView extends IUpdateable {
void setPlayerChangeListener(IPlayerChangeListener iPlayerChangeListener);
}

View File

@@ -1,12 +1,12 @@
package forge.interfaces;
public interface IProgressBar {
void setDescription(String s0);
void setValue(int progress);
void reset();
void setShowETA(boolean b0);
void setShowCount(boolean b0);
void setPercentMode(boolean percentMode0);
int getMaximum();
void setMaximum(int maximum0);
}
package forge.interfaces;
public interface IProgressBar {
void setDescription(String s0);
void setValue(int progress);
void reset();
void setShowETA(boolean b0);
void setShowCount(boolean b0);
void setPercentMode(boolean percentMode0);
int getMaximum();
void setMaximum(int maximum0);
}

View File

@@ -1,5 +1,5 @@
package forge.interfaces;
public interface ITextField extends ITextComponent {
boolean requestFocusInWindow();
}
package forge.interfaces;
public interface ITextField extends ITextComponent {
boolean requestFocusInWindow();
}

View File

@@ -1,17 +1,17 @@
package forge.interfaces;
import java.util.List;
import forge.assets.FSkinProp;
import forge.item.PaperCard;
public interface IWinLoseView<T extends IButton> {
T getBtnContinue();
T getBtnRestart();
T getBtnQuit();
void hide();
void showRewards(Runnable runnable);
void showCards(String title, List<PaperCard> cards);
void showMessage(String message, String title, FSkinProp icon);
}
package forge.interfaces;
import java.util.List;
import forge.assets.FSkinProp;
import forge.item.PaperCard;
public interface IWinLoseView<T extends IButton> {
T getBtnContinue();
T getBtnRestart();
T getBtnQuit();
void hide();
void showRewards(Runnable runnable);
void showCards(String title, List<PaperCard> cards);
void showMessage(String message, String title, FSkinProp icon);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,171 +1,171 @@
package forge.itemmanager;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.util.PredicateString.StringOp;
import java.util.*;
public class BooleanExpression {
private Stack<Operator> operators = new Stack<>();
private Stack<Predicate<CardRules>> operands = new Stack<>();
private StringTokenizer expression;
private boolean inName, inType, inText, inCost;
public enum Operator {
AND("&", 0), OR("|", 0), NOT("!", 1), OPEN_PAREN("(", 2), CLOSE_PAREN(")", 2), ESCAPE("\\", -1);
private final String token;
private final int precedence;
Operator(final String token, final int precedence) {
this.token = token;
this.precedence = precedence;
}
public String toString() {
return this.token;
}
}
public BooleanExpression(final String expression, final boolean inName, final boolean inType, final boolean inText, final boolean inCost) {
this.expression = new StringTokenizer(expression);
this.inName = inName;
this.inType = inType;
this.inText = inText;
this.inCost = inCost;
}
public Predicate<CardRules> evaluate() {
String currentValue = "";
boolean escapeNext = false;
while (expression.hasNext()) {
String token = expression.next();
Operator operator = null;
if (token.equals(Operator.AND.token)) {
operator = Operator.AND;
} else if (token.equals(Operator.OR.token)) {
operator = Operator.OR;
} else if (token.equals(Operator.OPEN_PAREN.token)) {
operator = Operator.OPEN_PAREN;
} else if (token.equals(Operator.CLOSE_PAREN.token)) {
operator = Operator.CLOSE_PAREN;
} else if (token.equals(Operator.NOT.token) && currentValue.trim().isEmpty()) { //Ignore ! operators that aren't the first token in a search term (Don't use '!' in 'Kaboom!')
operator = Operator.NOT;
} else if (token.equals(Operator.ESCAPE.token)) {
escapeNext = true;
continue;
}
if (operator == null) {
currentValue += token;
} else {
if (escapeNext) {
escapeNext = false;
currentValue += token;
continue;
}
if (!currentValue.trim().isEmpty()) {
operands.push(valueOf(currentValue.trim()));
}
currentValue = "";
if (!operators.isEmpty() && operator.precedence < operators.peek().precedence) {
resolve(true);
} else if (!operators.isEmpty() && operator == Operator.CLOSE_PAREN) {
while (!operators.isEmpty() && operators.peek() != Operator.OPEN_PAREN) {
resolve(true);
}
}
operators.push(operator);
}
}
if (!currentValue.trim().isEmpty()) {
operands.push(valueOf(currentValue.trim()));
}
while (!operators.isEmpty()) {
resolve(true);
}
return operands.get(0);
}
private void resolve(final boolean alwaysPopOperator) {
Predicate<CardRules> right;
Predicate<CardRules> left;
switch (operators.peek()) {
case AND:
operators.pop();
right = operands.pop();
left = operands.pop();
operands.push(Predicates.and(left, right));
break;
case OR:
operators.pop();
right = operands.pop();
left = operands.pop();
operands.push(Predicates.or(left, right));
break;
case NOT:
operators.pop();
left = operands.pop();
operands.push(Predicates.not(left));
break;
default:
if (alwaysPopOperator) {
operators.pop();
}
break;
}
}
private Predicate<CardRules> valueOf(final String value) {
List<Predicate<CardRules>> predicates = new ArrayList<>();
if (inName) {
predicates.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, value));
}
if (inType) {
predicates.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, value));
}
if (inText) {
predicates.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, value));
}
if (inCost) {
predicates.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, value));
}
if (!predicates.isEmpty()) {
return Predicates.or(predicates);
}
return Predicates.alwaysTrue();
}
public static boolean isExpression(final String string) {
return string.contains(Operator.AND.token) || string.contains(Operator.OR.token) || string.trim().startsWith(Operator.NOT.token);
}
}
package forge.itemmanager;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.util.PredicateString.StringOp;
import java.util.*;
public class BooleanExpression {
private Stack<Operator> operators = new Stack<>();
private Stack<Predicate<CardRules>> operands = new Stack<>();
private StringTokenizer expression;
private boolean inName, inType, inText, inCost;
public enum Operator {
AND("&", 0), OR("|", 0), NOT("!", 1), OPEN_PAREN("(", 2), CLOSE_PAREN(")", 2), ESCAPE("\\", -1);
private final String token;
private final int precedence;
Operator(final String token, final int precedence) {
this.token = token;
this.precedence = precedence;
}
public String toString() {
return this.token;
}
}
public BooleanExpression(final String expression, final boolean inName, final boolean inType, final boolean inText, final boolean inCost) {
this.expression = new StringTokenizer(expression);
this.inName = inName;
this.inType = inType;
this.inText = inText;
this.inCost = inCost;
}
public Predicate<CardRules> evaluate() {
String currentValue = "";
boolean escapeNext = false;
while (expression.hasNext()) {
String token = expression.next();
Operator operator = null;
if (token.equals(Operator.AND.token)) {
operator = Operator.AND;
} else if (token.equals(Operator.OR.token)) {
operator = Operator.OR;
} else if (token.equals(Operator.OPEN_PAREN.token)) {
operator = Operator.OPEN_PAREN;
} else if (token.equals(Operator.CLOSE_PAREN.token)) {
operator = Operator.CLOSE_PAREN;
} else if (token.equals(Operator.NOT.token) && currentValue.trim().isEmpty()) { //Ignore ! operators that aren't the first token in a search term (Don't use '!' in 'Kaboom!')
operator = Operator.NOT;
} else if (token.equals(Operator.ESCAPE.token)) {
escapeNext = true;
continue;
}
if (operator == null) {
currentValue += token;
} else {
if (escapeNext) {
escapeNext = false;
currentValue += token;
continue;
}
if (!currentValue.trim().isEmpty()) {
operands.push(valueOf(currentValue.trim()));
}
currentValue = "";
if (!operators.isEmpty() && operator.precedence < operators.peek().precedence) {
resolve(true);
} else if (!operators.isEmpty() && operator == Operator.CLOSE_PAREN) {
while (!operators.isEmpty() && operators.peek() != Operator.OPEN_PAREN) {
resolve(true);
}
}
operators.push(operator);
}
}
if (!currentValue.trim().isEmpty()) {
operands.push(valueOf(currentValue.trim()));
}
while (!operators.isEmpty()) {
resolve(true);
}
return operands.get(0);
}
private void resolve(final boolean alwaysPopOperator) {
Predicate<CardRules> right;
Predicate<CardRules> left;
switch (operators.peek()) {
case AND:
operators.pop();
right = operands.pop();
left = operands.pop();
operands.push(Predicates.and(left, right));
break;
case OR:
operators.pop();
right = operands.pop();
left = operands.pop();
operands.push(Predicates.or(left, right));
break;
case NOT:
operators.pop();
left = operands.pop();
operands.push(Predicates.not(left));
break;
default:
if (alwaysPopOperator) {
operators.pop();
}
break;
}
}
private Predicate<CardRules> valueOf(final String value) {
List<Predicate<CardRules>> predicates = new ArrayList<>();
if (inName) {
predicates.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, value));
}
if (inType) {
predicates.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, value));
}
if (inText) {
predicates.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, value));
}
if (inCost) {
predicates.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, value));
}
if (!predicates.isEmpty()) {
return Predicates.or(predicates);
}
return Predicates.alwaysTrue();
}
public static boolean isExpression(final String string) {
return string.contains(Operator.AND.token) || string.contains(Operator.OR.token) || string.trim().startsWith(Operator.NOT.token);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,275 +1,275 @@
package forge.itemmanager;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import forge.card.CardEdition;
import forge.card.CardType;
import forge.card.ColorSet;
import forge.deck.DeckProxy;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.model.FModel;
public enum GroupDef {
COLOR("Color", getColorGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getColorGroup(((PaperCard) item).getRules().getColor());
}
else if (item instanceof DeckProxy) {
return getColorGroup(((DeckProxy) item).getColor());
}
return -1;
}
}),
COLOR_IDENTITY("Color Identity", getColorGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getColorGroup(((PaperCard) item).getRules().getColorIdentity());
}
else if (item instanceof DeckProxy) {
return getColorGroup(((DeckProxy) item).getColorIdentity());
}
return -1;
}
}),
SET("Set", getSetGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getSetGroup(((PaperCard) item).getEdition());
}
else if (item instanceof DeckProxy) {
return getSetGroup(((DeckProxy) item).getEdition().getCode());
}
return -1;
}
}),
DEFAULT("Default",
new String[] { "Creatures", "Spells", "Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
if (groupIndex == 2) {
return ColumnDef.NAME; //pile lands by name regardless
}
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
CardType type = ((PaperCard) item).getRules().getType();
if (type.isCreature()) {
return 0;
}
if (type.isLand()) { //make Artifact Lands appear in Lands group
return 2;
}
if (type.isArtifact() || type.isEnchantment() || type.isPlaneswalker() || type.isInstant() || type.isSorcery()) {
return 1;
}
}
return -1;
}
}),
CARD_TYPE("Type",
new String[] { "Creatures", "Artifacts", "Enchantments", "Planeswalkers", "Instants", "Sorceries", "Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
if (groupIndex == 6) {
return ColumnDef.NAME; //pile lands by name regardless
}
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
CardType type = ((PaperCard) item).getRules().getType();
if (type.isCreature()) { //make Artifact and Land Creatures appear in Creatures group
return 0;
}
if (type.isLand()) { //make Artifact Lands appear in Lands group
return 6;
}
if (type.isArtifact()) {
return 1;
}
if (type.isEnchantment()) {
return 2;
}
if (type.isPlaneswalker()) {
return 3;
}
if (type.isInstant()) {
return 4;
}
if (type.isSorcery()) {
return 5;
}
}
return -1;
}
}),
CARD_RARITY("Rarity",
new String[] { "Mythic Rares", "Rares", "Uncommons", "Commons", "Basic Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
switch (((PaperCard) item).getRarity()) {
case MythicRare:
return 0;
case Rare:
return 1;
case Uncommon:
return 2;
case Common:
return 3;
case BasicLand:
return 4;
default:
return -1; //show Special and Unknown in "Other" group
}
}
return -1;
}
});
GroupDef(String name0, String[] groups0, Function<Integer, ColumnDef> fnGetPileByOverride0, Function<InventoryItem, Integer> fnGroupItem0) {
this.name = name0;
this.groups = groups0;
this.fnGetPileByOverride = fnGetPileByOverride0;
this.fnGroupItem = fnGroupItem0;
}
private final String name;
private final String[] groups;
private final Function<Integer, ColumnDef> fnGetPileByOverride;
private final Function<InventoryItem, Integer> fnGroupItem;
public String getName() {
return this.name;
}
@Override
public String toString() {
return this.name;
}
public String[] getGroups() {
return this.groups;
}
public ColumnDef getGroupPileBy(int groupIndex, ColumnDef defaultPileBy) {
ColumnDef pileBy = this.fnGetPileByOverride.apply(groupIndex);
if (pileBy == null) {
return defaultPileBy;
}
return pileBy;
}
public int getItemGroupIndex(InventoryItem item) {
return this.fnGroupItem.apply(item);
}
private static String[] getColorGroups() {
//TODO: Support breaking up Multicolor into separate groups for each color combination
return new String[] { "White", "Blue", "Black", "Red", "Green", "Multicolor", "Colorless" };
}
private static Integer getColorGroup(ColorSet color) {
if (color == null) {
return -1;
}
if (color.isColorless()) {
return 6;
}
if (color.isMulticolor()) {
return 5;
}
if (color.hasWhite()) {
return 0;
}
if (color.hasBlue()) {
return 1;
}
if (color.hasBlack()) {
return 2;
}
if (color.hasRed()) {
return 3;
}
if (color.hasGreen()) {
return 4;
}
return -1; //shouldn't happen
}
private static Map<String, Integer> setGroupMap;
private static String[] getSetGroups() {
setGroupMap = new HashMap<String, Integer>(); //cache mappings to make lookup quicker later
//build sorted list of sets
List<CardEdition> sortedSets = Lists.newArrayList(FModel.getMagicDb().getEditions());
Collections.sort(sortedSets);
Collections.reverse(sortedSets);
int groupNum = 0;
String[] setGroups = new String[sortedSets.size()];
for (CardEdition set : sortedSets) {
setGroups[groupNum] = set.getName();
setGroupMap.put(set.getCode(), groupNum);
groupNum++;
}
return setGroups;
}
private static Integer getSetGroup(String set) {
Integer groupNum = setGroupMap.get(set);
if (groupNum == null) {
groupNum = -1;
}
return groupNum;
}
}
package forge.itemmanager;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import forge.card.CardEdition;
import forge.card.CardType;
import forge.card.ColorSet;
import forge.deck.DeckProxy;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.model.FModel;
public enum GroupDef {
COLOR("Color", getColorGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getColorGroup(((PaperCard) item).getRules().getColor());
}
else if (item instanceof DeckProxy) {
return getColorGroup(((DeckProxy) item).getColor());
}
return -1;
}
}),
COLOR_IDENTITY("Color Identity", getColorGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getColorGroup(((PaperCard) item).getRules().getColorIdentity());
}
else if (item instanceof DeckProxy) {
return getColorGroup(((DeckProxy) item).getColorIdentity());
}
return -1;
}
}),
SET("Set", getSetGroups(),
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
return getSetGroup(((PaperCard) item).getEdition());
}
else if (item instanceof DeckProxy) {
return getSetGroup(((DeckProxy) item).getEdition().getCode());
}
return -1;
}
}),
DEFAULT("Default",
new String[] { "Creatures", "Spells", "Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
if (groupIndex == 2) {
return ColumnDef.NAME; //pile lands by name regardless
}
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
CardType type = ((PaperCard) item).getRules().getType();
if (type.isCreature()) {
return 0;
}
if (type.isLand()) { //make Artifact Lands appear in Lands group
return 2;
}
if (type.isArtifact() || type.isEnchantment() || type.isPlaneswalker() || type.isInstant() || type.isSorcery()) {
return 1;
}
}
return -1;
}
}),
CARD_TYPE("Type",
new String[] { "Creatures", "Artifacts", "Enchantments", "Planeswalkers", "Instants", "Sorceries", "Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
if (groupIndex == 6) {
return ColumnDef.NAME; //pile lands by name regardless
}
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
CardType type = ((PaperCard) item).getRules().getType();
if (type.isCreature()) { //make Artifact and Land Creatures appear in Creatures group
return 0;
}
if (type.isLand()) { //make Artifact Lands appear in Lands group
return 6;
}
if (type.isArtifact()) {
return 1;
}
if (type.isEnchantment()) {
return 2;
}
if (type.isPlaneswalker()) {
return 3;
}
if (type.isInstant()) {
return 4;
}
if (type.isSorcery()) {
return 5;
}
}
return -1;
}
}),
CARD_RARITY("Rarity",
new String[] { "Mythic Rares", "Rares", "Uncommons", "Commons", "Basic Lands" },
new Function<Integer, ColumnDef>() {
@Override
public ColumnDef apply(final Integer groupIndex) {
return null;
}
},
new Function<InventoryItem, Integer>() {
@Override
public Integer apply(final InventoryItem item) {
if (item instanceof PaperCard) {
switch (((PaperCard) item).getRarity()) {
case MythicRare:
return 0;
case Rare:
return 1;
case Uncommon:
return 2;
case Common:
return 3;
case BasicLand:
return 4;
default:
return -1; //show Special and Unknown in "Other" group
}
}
return -1;
}
});
GroupDef(String name0, String[] groups0, Function<Integer, ColumnDef> fnGetPileByOverride0, Function<InventoryItem, Integer> fnGroupItem0) {
this.name = name0;
this.groups = groups0;
this.fnGetPileByOverride = fnGetPileByOverride0;
this.fnGroupItem = fnGroupItem0;
}
private final String name;
private final String[] groups;
private final Function<Integer, ColumnDef> fnGetPileByOverride;
private final Function<InventoryItem, Integer> fnGroupItem;
public String getName() {
return this.name;
}
@Override
public String toString() {
return this.name;
}
public String[] getGroups() {
return this.groups;
}
public ColumnDef getGroupPileBy(int groupIndex, ColumnDef defaultPileBy) {
ColumnDef pileBy = this.fnGetPileByOverride.apply(groupIndex);
if (pileBy == null) {
return defaultPileBy;
}
return pileBy;
}
public int getItemGroupIndex(InventoryItem item) {
return this.fnGroupItem.apply(item);
}
private static String[] getColorGroups() {
//TODO: Support breaking up Multicolor into separate groups for each color combination
return new String[] { "White", "Blue", "Black", "Red", "Green", "Multicolor", "Colorless" };
}
private static Integer getColorGroup(ColorSet color) {
if (color == null) {
return -1;
}
if (color.isColorless()) {
return 6;
}
if (color.isMulticolor()) {
return 5;
}
if (color.hasWhite()) {
return 0;
}
if (color.hasBlue()) {
return 1;
}
if (color.hasBlack()) {
return 2;
}
if (color.hasRed()) {
return 3;
}
if (color.hasGreen()) {
return 4;
}
return -1; //shouldn't happen
}
private static Map<String, Integer> setGroupMap;
private static String[] getSetGroups() {
setGroupMap = new HashMap<String, Integer>(); //cache mappings to make lookup quicker later
//build sorted list of sets
List<CardEdition> sortedSets = Lists.newArrayList(FModel.getMagicDb().getEditions());
Collections.sort(sortedSets);
Collections.reverse(sortedSets);
int groupNum = 0;
String[] setGroups = new String[sortedSets.size()];
for (CardEdition set : sortedSets) {
setGroups[groupNum] = set.getName();
setGroupMap.put(set.getCode(), groupNum);
groupNum++;
}
return setGroups;
}
private static Integer getSetGroup(String set) {
Integer groupNum = setGroupMap.get(set);
if (groupNum == null) {
groupNum = -1;
}
return groupNum;
}
}

View File

@@ -1,46 +1,46 @@
package forge.itemmanager;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import forge.item.InventoryItem;
import forge.util.ItemPool;
public interface IItemManager<T extends InventoryItem> {
ItemManagerConfig getConfig();
void setup(ItemManagerConfig config0);
Class<T> getGenericType();
String getCaption();
void setCaption(String caption);
ItemPool<T> getPool();
void setPool(final Iterable<T> items);
void setPool(final ItemPool<T> poolView, boolean infinite);
void setPool(final ItemPool<T> pool0);
int getItemCount();
int getSelectionCount();
T getSelectedItem();
Collection<T> getSelectedItems();
ItemPool<T> getSelectedItemPool();
boolean setSelectedItem(T item);
boolean setSelectedItems(Iterable<T> items);
T stringToItem(String str);
boolean setSelectedString(String str);
boolean setSelectedStrings(Iterable<String> strings);
boolean selectItemEntrys(Iterable<Entry<T, Integer>> itemEntrys);
void selectAll();
int getSelectedIndex();
Iterable<Integer> getSelectedIndices();
void setSelectedIndex(int index);
void setSelectedIndices(Integer[] indices);
void setSelectedIndices(Iterable<Integer> indices);
void addItem(final T item, int qty);
void addItems(Iterable<Entry<T, Integer>> itemsToAdd);
void removeItem(final T item, int qty);
void removeItems(Iterable<Map.Entry<T, Integer>> itemsToRemove);
void removeAllItems();
void scrollSelectionIntoView();
int getItemCount(final T item);
ItemPool<T> getFilteredItems();
boolean applyFilters();
}
package forge.itemmanager;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import forge.item.InventoryItem;
import forge.util.ItemPool;
public interface IItemManager<T extends InventoryItem> {
ItemManagerConfig getConfig();
void setup(ItemManagerConfig config0);
Class<T> getGenericType();
String getCaption();
void setCaption(String caption);
ItemPool<T> getPool();
void setPool(final Iterable<T> items);
void setPool(final ItemPool<T> poolView, boolean infinite);
void setPool(final ItemPool<T> pool0);
int getItemCount();
int getSelectionCount();
T getSelectedItem();
Collection<T> getSelectedItems();
ItemPool<T> getSelectedItemPool();
boolean setSelectedItem(T item);
boolean setSelectedItems(Iterable<T> items);
T stringToItem(String str);
boolean setSelectedString(String str);
boolean setSelectedStrings(Iterable<String> strings);
boolean selectItemEntrys(Iterable<Entry<T, Integer>> itemEntrys);
void selectAll();
int getSelectedIndex();
Iterable<Integer> getSelectedIndices();
void setSelectedIndex(int index);
void setSelectedIndices(Integer[] indices);
void setSelectedIndices(Iterable<Integer> indices);
void addItem(final T item, int qty);
void addItems(Iterable<Entry<T, Integer>> itemsToAdd);
void removeItem(final T item, int qty);
void removeItems(Iterable<Map.Entry<T, Integer>> itemsToRemove);
void removeAllItems();
void scrollSelectionIntoView();
int getItemCount(final T item);
ItemPool<T> getFilteredItems();
boolean applyFilters();
}

View File

@@ -1,122 +1,122 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import com.google.common.base.Function;
import forge.item.InventoryItem;
import forge.itemmanager.ItemColumnConfig.SortState;
import java.util.Map;
import java.util.Map.Entry;
public class ItemColumn {
private final ItemColumnConfig config;
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort;
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay;
public ItemColumn(ItemColumnConfig config0) {
this(config0, config0.getFnSort(), config0.getFnDisplay());
}
public ItemColumn(ItemColumnConfig config0,
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
if (fnSort0 == null) {
throw new NullPointerException("A sort function hasn't been set for column " + config0.getLongName());
}
if (fnDisplay0 == null) {
throw new NullPointerException("A display function hasn't been set for column " + config0.getLongName());
}
config = config0;
fnSort = fnSort0;
fnDisplay = fnDisplay0;
}
public ItemColumnConfig getConfig() {
return config;
}
public String getShortName() {
return config.getShortName();
}
public String getLongName() {
return config.getLongName();
}
public int getIndex() {
return config.getIndex();
}
public void setIndex(final int index0) {
config.setIndex(index0);
}
public int getSortPriority() {
return config.getSortPriority();
}
public void setSortPriority(final int sortPriority0) {
config.setSortPriority(sortPriority0);
}
public SortState getSortState() {
return config.getSortState();
}
public void setSortState(final SortState state0) {
config.setSortState(state0);
}
public SortState getDefaultSortState() {
return config.getDefaultSortState();
}
public boolean isVisible() {
return config.isVisible();
}
public void setVisible(boolean visible0) {
config.setVisible(visible0);
}
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
return fnSort;
}
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
return fnDisplay;
}
@Override
public String toString() {
return config.getLongName();
}
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef) {
ItemColumnConfig colConfig = config.getCols().get(colDef);
addColOverride(config, colOverrides, colDef, colConfig.getFnSort(), colConfig.getFnDisplay());
}
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef,
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
colOverrides.put(colDef, new ItemColumn(config.getCols().get(colDef), fnSort0, fnDisplay0));
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import com.google.common.base.Function;
import forge.item.InventoryItem;
import forge.itemmanager.ItemColumnConfig.SortState;
import java.util.Map;
import java.util.Map.Entry;
public class ItemColumn {
private final ItemColumnConfig config;
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort;
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay;
public ItemColumn(ItemColumnConfig config0) {
this(config0, config0.getFnSort(), config0.getFnDisplay());
}
public ItemColumn(ItemColumnConfig config0,
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
if (fnSort0 == null) {
throw new NullPointerException("A sort function hasn't been set for column " + config0.getLongName());
}
if (fnDisplay0 == null) {
throw new NullPointerException("A display function hasn't been set for column " + config0.getLongName());
}
config = config0;
fnSort = fnSort0;
fnDisplay = fnDisplay0;
}
public ItemColumnConfig getConfig() {
return config;
}
public String getShortName() {
return config.getShortName();
}
public String getLongName() {
return config.getLongName();
}
public int getIndex() {
return config.getIndex();
}
public void setIndex(final int index0) {
config.setIndex(index0);
}
public int getSortPriority() {
return config.getSortPriority();
}
public void setSortPriority(final int sortPriority0) {
config.setSortPriority(sortPriority0);
}
public SortState getSortState() {
return config.getSortState();
}
public void setSortState(final SortState state0) {
config.setSortState(state0);
}
public SortState getDefaultSortState() {
return config.getDefaultSortState();
}
public boolean isVisible() {
return config.isVisible();
}
public void setVisible(boolean visible0) {
config.setVisible(visible0);
}
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
return fnSort;
}
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
return fnDisplay;
}
@Override
public String toString() {
return config.getLongName();
}
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef) {
ItemColumnConfig colConfig = config.getCols().get(colDef);
addColOverride(config, colOverrides, colDef, colConfig.getFnSort(), colConfig.getFnDisplay());
}
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef,
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
colOverrides.put(colDef, new ItemColumn(config.getCols().get(colDef), fnSort0, fnDisplay0));
}
}

View File

@@ -1,120 +1,120 @@
package forge.itemmanager;
import java.util.Map.Entry;
import com.google.common.base.Function;
import forge.item.InventoryItem;
public class ItemColumnConfig {
public static enum SortState {
NONE,
ASC,
DESC
}
private final ColumnDef def;
private SortState sortState = SortState.NONE;
private int preferredWidth;
private int sortPriority = 0;
private boolean visible = true;
private int index = 0;
private ItemColumnConfig defaults;
public ItemColumnConfig(ColumnDef def0) {
this.def = def0;
this.preferredWidth = def0.preferredWidth;
}
private ItemColumnConfig(ItemColumnConfig from) {
this.def = from.def;
this.sortState = from.sortState;
this.preferredWidth = from.preferredWidth;
this.sortPriority = from.sortPriority;
this.visible = from.visible;
this.index = from.index;
}
public ColumnDef getDef() {
return this.def;
}
public String getShortName() {
return this.def.shortName;
}
public String getLongName() {
return this.def.longName;
}
public int getPreferredWidth() {
return this.preferredWidth;
}
public void setPreferredWidth(int preferredWidth0) {
this.preferredWidth = preferredWidth0;
}
public int getIndex() {
return this.index;
}
public void setIndex(final int index0) {
this.index = index0;
}
public int getSortPriority() {
return sortPriority;
}
public void setSortPriority(final int sortPriority0) {
int oldSortPriority = this.sortPriority;
this.sortPriority = sortPriority0;
if (sortPriority0 == 0) {
this.sortState = SortState.NONE;
}
else if (oldSortPriority == 0) {
this.sortState = def.sortState;
}
}
public SortState getSortState() {
return this.sortState;
}
public void setSortState(final SortState state0) {
this.sortState = state0;
}
public SortState getDefaultSortState() {
return this.def.sortState;
}
public boolean isVisible() {
return this.visible;
}
public void setVisible(boolean visible0) {
this.visible = visible0;
}
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
return this.def.fnSort;
}
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
return this.def.fnDisplay;
}
@Override
public String toString() {
return this.getLongName();
}
public void establishDefaults() {
this.defaults = new ItemColumnConfig(this);
}
public ItemColumnConfig getDefaults() {
return this.defaults;
}
}
package forge.itemmanager;
import java.util.Map.Entry;
import com.google.common.base.Function;
import forge.item.InventoryItem;
public class ItemColumnConfig {
public static enum SortState {
NONE,
ASC,
DESC
}
private final ColumnDef def;
private SortState sortState = SortState.NONE;
private int preferredWidth;
private int sortPriority = 0;
private boolean visible = true;
private int index = 0;
private ItemColumnConfig defaults;
public ItemColumnConfig(ColumnDef def0) {
this.def = def0;
this.preferredWidth = def0.preferredWidth;
}
private ItemColumnConfig(ItemColumnConfig from) {
this.def = from.def;
this.sortState = from.sortState;
this.preferredWidth = from.preferredWidth;
this.sortPriority = from.sortPriority;
this.visible = from.visible;
this.index = from.index;
}
public ColumnDef getDef() {
return this.def;
}
public String getShortName() {
return this.def.shortName;
}
public String getLongName() {
return this.def.longName;
}
public int getPreferredWidth() {
return this.preferredWidth;
}
public void setPreferredWidth(int preferredWidth0) {
this.preferredWidth = preferredWidth0;
}
public int getIndex() {
return this.index;
}
public void setIndex(final int index0) {
this.index = index0;
}
public int getSortPriority() {
return sortPriority;
}
public void setSortPriority(final int sortPriority0) {
int oldSortPriority = this.sortPriority;
this.sortPriority = sortPriority0;
if (sortPriority0 == 0) {
this.sortState = SortState.NONE;
}
else if (oldSortPriority == 0) {
this.sortState = def.sortState;
}
}
public SortState getSortState() {
return this.sortState;
}
public void setSortState(final SortState state0) {
this.sortState = state0;
}
public SortState getDefaultSortState() {
return this.def.sortState;
}
public boolean isVisible() {
return this.visible;
}
public void setVisible(boolean visible0) {
this.visible = visible0;
}
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
return this.def.fnSort;
}
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
return this.def.fnDisplay;
}
@Override
public String toString() {
return this.getLongName();
}
public void establishDefaults() {
this.defaults = new ItemColumnConfig(this);
}
public ItemColumnConfig getDefaults() {
return this.defaults;
}
}

View File

@@ -1,352 +1,352 @@
package forge.itemmanager;
import forge.itemmanager.ItemColumnConfig.SortState;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences.FPref;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual cards
*
*/
public enum ItemManagerConfig {
STRING_ONLY(SColumnUtil.getStringColumn(), false, false, true,
null, null, 1, 0),
CARD_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
null, null, 4, 0),
DECK_EDITOR(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
DRAFT_PACK(SColumnUtil.getDraftPackDefaultColumns(), false, false, true,
null, null, 4, 1),
DRAFT_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
DRAFT_CONSPIRACY(SColumnUtil.getSpecialCardPoolDefaultColumns(), false, false, true,
null, null, 4, 0),
SEALED_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
GroupDef.COLOR, ColumnDef.CMC, 4, 1),
SPELL_SHOP(SColumnUtil.getSpellShopDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_INVENTORY(SColumnUtil.getQuestInventoryDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_EDITOR_POOL(SColumnUtil.getQuestEditorPoolDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_DECK_EDITOR(SColumnUtil.getQuestDeckEditorDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
QUEST_DRAFT_DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
CONQUEST_AETHER(SColumnUtil.getConquestAEtherDefaultColumns(), false, false, false,
null, null, 4, 0),
CONQUEST_COMMANDERS(SColumnUtil.getConquestCommandersDefaultColumns(), false, false, false,
null, null, 3, 0),
CONQUEST_COLLECTION(SColumnUtil.getConquestCollectionDefaultColumns(), false, false, false,
null, null, 4, 0),
CONQUEST_DECK_EDITOR(SColumnUtil.getConquestDeckEditorDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
AVATAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, false,
null, null, 4, 0),
SCHEME_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
CONSPIRACY_DECKS(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
SCHEME_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 4, 0),
PLANAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
PLANAR_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 4, 0),
COMMANDER_POOL(SColumnUtil.getCatalogDefaultColumns(true), true, false, false,
null, null, 4, 0),
COMMANDER_SECTION(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 1, 1),
WORKSHOP_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
null, null, 4, 0),
DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
CONSTRUCTED_DECKS(SColumnUtil.getDecksDefaultColumns(true, true), false, false, false,
null, null, 3, 0),
COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
PLANAR_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
SCHEME_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
VANGUARDS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, true,
null, null, 3, 0),
DRAFT_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
SEALED_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
WINSTON_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
QUEST_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
PRECON_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
QUEST_EVENT_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
SIDEBOARD(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 3, 0);
private Map<ColumnDef, ItemColumnConfig> cols;
private boolean showUniqueCardsOption;
private Prop<Boolean> uniqueCardsOnly;
private Prop<Boolean> hideFilters;
private Prop<Boolean> compactListView;
private Prop<GroupDef> groupBy;
private Prop<ColumnDef> pileBy;
private Prop<Integer> imageColumnCount;
private Prop<Integer> viewIndex;
private ItemManagerConfig(final Map<ColumnDef, ItemColumnConfig> cols0, boolean showUniqueCardsOption0, boolean uniqueCardsOnly0, boolean hideFilters0, GroupDef groupBy0, ColumnDef pileBy0, int imageColumnCount0, int viewIndex0) {
cols = cols0;
for (ItemColumnConfig colConfig : cols.values()) {
colConfig.establishDefaults();
}
showUniqueCardsOption = showUniqueCardsOption0;
uniqueCardsOnly = new Prop<Boolean>(uniqueCardsOnly0);
hideFilters = new Prop<Boolean>(hideFilters0);
compactListView = new Prop<Boolean>(FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_LIST_ITEMS)); //use main setting to determine default
groupBy = new Prop<GroupDef>(groupBy0);
pileBy = new Prop<ColumnDef>(pileBy0);
imageColumnCount = new Prop<Integer>(imageColumnCount0);
viewIndex = new Prop<Integer>(viewIndex0);
}
private class Prop<T> {
private T value;
private T defaultValue;
private Prop(T defaultValue0) {
value = defaultValue0;
defaultValue = defaultValue0;
}
private T getValue() {
return value;
}
private void setValue(T value0) {
if (value == value0) { return; }
value = value0;
save();
}
@SuppressWarnings("rawtypes")
private void writeValue(final Element el, String localName) {
if (value == null) {
if (defaultValue != null) {
el.setAttribute(localName, "");
}
}
else if (!value.equals(defaultValue)) {
if (value instanceof Enum) { //use Enum.name to prevent issues with toString() overrides
el.setAttribute(localName, ((Enum)value).name());
}
else {
el.setAttribute(localName, String.valueOf(value));
}
}
}
}
public Map<ColumnDef, ItemColumnConfig> getCols() {
return cols;
}
public boolean getShowUniqueCardsOption() {
return showUniqueCardsOption;
}
public boolean getUniqueCardsOnly() {
return uniqueCardsOnly.getValue();
}
public void setUniqueCardsOnly(boolean value0) {
uniqueCardsOnly.setValue(value0);
}
public boolean getHideFilters() {
return hideFilters.getValue();
}
public void setHideFilters(boolean value0) {
hideFilters.setValue(value0);
}
public boolean getCompactListView() {
return compactListView.getValue();
}
public void setCompactListView(boolean value0) {
compactListView.setValue(value0);
}
public GroupDef getGroupBy() {
return groupBy.getValue();
}
public void setGroupBy(GroupDef value0) {
groupBy.setValue(value0);
}
public ColumnDef getPileBy() {
return pileBy.getValue();
}
public void setPileBy(ColumnDef value0) {
pileBy.setValue(value0);
}
public int getImageColumnCount() {
return imageColumnCount.getValue();
}
public void setImageColumnCount(int value0) {
imageColumnCount.setValue(value0);
}
public int getViewIndex() {
return viewIndex.getValue();
}
public void setViewIndex(int value0) {
viewIndex.setValue(value0);
}
public static void load() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.ITEM_VIEW_PREFS_FILE));
final NodeList configs = document.getElementsByTagName("config");
for (int i = 0; i < configs.getLength(); i++) {
try { //capture enum parse errors without losing other preferences
final Element el = (Element)configs.item(i);
final ItemManagerConfig config = Enum.valueOf(ItemManagerConfig.class, el.getAttribute("name"));
if (el.hasAttribute("uniqueCardsOnly")) {
config.uniqueCardsOnly.value = Boolean.parseBoolean(el.getAttribute("uniqueCardsOnly"));
}
if (el.hasAttribute("hideFilters")) {
config.hideFilters.value = Boolean.parseBoolean(el.getAttribute("hideFilters"));
}
if (el.hasAttribute("compactListView")) {
config.compactListView.value = Boolean.parseBoolean(el.getAttribute("compactListView"));
}
if (el.hasAttribute("groupBy")) {
String value = el.getAttribute("groupBy");
if (value.isEmpty()) {
config.groupBy.value = null;
}
else {
config.groupBy.value = Enum.valueOf(GroupDef.class, value);
}
}
if (el.hasAttribute("pileBy")) {
String value = el.getAttribute("pileBy");
if (value.isEmpty()) {
config.pileBy.value = null;
}
else {
config.pileBy.value = Enum.valueOf(ColumnDef.class, value);
}
}
if (el.hasAttribute("imageColumnCount")) {
config.imageColumnCount.value = Integer.parseInt(el.getAttribute("imageColumnCount"));
}
if (el.hasAttribute("viewIndex")) {
config.viewIndex.value = Integer.parseInt(el.getAttribute("viewIndex"));
}
final NodeList cols = el.getElementsByTagName("col");
for (int j = 0; j < cols.getLength(); j++) {
try { //capture enum parse errors without losing other column preferences
final Element colEl = (Element)cols.item(j);
ItemColumnConfig colConfig = config.cols.get(Enum.valueOf(ColumnDef.class, colEl.getAttribute("name")));
if (colEl.hasAttribute("width")) {
colConfig.setPreferredWidth(Integer.parseInt(colEl.getAttribute("width")));
}
if (colEl.hasAttribute("sortPriority")) {
colConfig.setSortPriority(Integer.parseInt(colEl.getAttribute("sortPriority")));
}
if (colEl.hasAttribute("sortState")) {
colConfig.setSortState(Enum.valueOf(SortState.class, colEl.getAttribute("sortState")));
}
if (colEl.hasAttribute("index")) {
colConfig.setIndex(Integer.parseInt(colEl.getAttribute("index")));
}
if (colEl.hasAttribute("visible")) {
colConfig.setVisible(Boolean.parseBoolean(colEl.getAttribute("visible")));
}
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "item_view");
document.appendChild(root);
for (ItemManagerConfig config : ItemManagerConfig.values()) {
Element el = document.createElement("config");
el.setAttribute("name", config.name());
config.uniqueCardsOnly.writeValue(el, "uniqueCardsOnly");
config.hideFilters.writeValue(el, "hideFilters");
config.compactListView.writeValue(el, "compactListView");
config.groupBy.writeValue(el, "groupBy");
config.pileBy.writeValue(el, "pileBy");
config.imageColumnCount.writeValue(el, "imageColumnCount");
config.viewIndex.writeValue(el, "viewIndex");
for (ItemColumnConfig colConfig : config.cols.values()) {
Element colEl = document.createElement("col");
colEl.setAttribute("name", colConfig.getDef().name());
if (colConfig.getPreferredWidth() != colConfig.getDefaults().getPreferredWidth()) {
colEl.setAttribute("width", String.valueOf(colConfig.getPreferredWidth()));
}
if (colConfig.getSortPriority() != colConfig.getDefaults().getSortPriority()) {
colEl.setAttribute("sortPriority", String.valueOf(colConfig.getSortPriority()));
}
if (colConfig.getSortState() != colConfig.getDefaults().getSortState()) {
colEl.setAttribute("sortState", String.valueOf(colConfig.getSortState()));
}
if (colConfig.getIndex() != colConfig.getDefaults().getIndex()) {
colEl.setAttribute("index", String.valueOf(colConfig.getIndex()));
}
if (colConfig.isVisible() != colConfig.getDefaults().isVisible()) {
colEl.setAttribute("visible", String.valueOf(colConfig.isVisible()));
}
el.appendChild(colEl);
}
root.appendChild(el);
}
XmlUtil.saveDocument(document, ForgeConstants.ITEM_VIEW_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
package forge.itemmanager;
import forge.itemmanager.ItemColumnConfig.SortState;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences.FPref;
import forge.util.XmlUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Preferences associated with individual cards
*
*/
public enum ItemManagerConfig {
STRING_ONLY(SColumnUtil.getStringColumn(), false, false, true,
null, null, 1, 0),
CARD_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
null, null, 4, 0),
DECK_EDITOR(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
DRAFT_PACK(SColumnUtil.getDraftPackDefaultColumns(), false, false, true,
null, null, 4, 1),
DRAFT_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
DRAFT_CONSPIRACY(SColumnUtil.getSpecialCardPoolDefaultColumns(), false, false, true,
null, null, 4, 0),
SEALED_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
GroupDef.COLOR, ColumnDef.CMC, 4, 1),
SPELL_SHOP(SColumnUtil.getSpellShopDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_INVENTORY(SColumnUtil.getQuestInventoryDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_EDITOR_POOL(SColumnUtil.getQuestEditorPoolDefaultColumns(), false, false, false,
null, null, 4, 0),
QUEST_DECK_EDITOR(SColumnUtil.getQuestDeckEditorDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
QUEST_DRAFT_DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
CONQUEST_AETHER(SColumnUtil.getConquestAEtherDefaultColumns(), false, false, false,
null, null, 4, 0),
CONQUEST_COMMANDERS(SColumnUtil.getConquestCommandersDefaultColumns(), false, false, false,
null, null, 3, 0),
CONQUEST_COLLECTION(SColumnUtil.getConquestCollectionDefaultColumns(), false, false, false,
null, null, 4, 0),
CONQUEST_DECK_EDITOR(SColumnUtil.getConquestDeckEditorDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
AVATAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, false,
null, null, 4, 0),
SCHEME_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
CONSPIRACY_DECKS(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
SCHEME_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 4, 0),
PLANAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
null, null, 4, 0),
PLANAR_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 4, 0),
COMMANDER_POOL(SColumnUtil.getCatalogDefaultColumns(true), true, false, false,
null, null, 4, 0),
COMMANDER_SECTION(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
null, null, 1, 1),
WORKSHOP_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
null, null, 4, 0),
DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, false,
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
CONSTRUCTED_DECKS(SColumnUtil.getDecksDefaultColumns(true, true), false, false, false,
null, null, 3, 0),
COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
PLANAR_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
SCHEME_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
VANGUARDS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, true,
null, null, 3, 0),
DRAFT_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
SEALED_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
WINSTON_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
QUEST_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
null, null, 3, 0),
PRECON_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
QUEST_EVENT_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
null, null, 3, 0),
SIDEBOARD(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
GroupDef.DEFAULT, ColumnDef.CMC, 3, 0);
private Map<ColumnDef, ItemColumnConfig> cols;
private boolean showUniqueCardsOption;
private Prop<Boolean> uniqueCardsOnly;
private Prop<Boolean> hideFilters;
private Prop<Boolean> compactListView;
private Prop<GroupDef> groupBy;
private Prop<ColumnDef> pileBy;
private Prop<Integer> imageColumnCount;
private Prop<Integer> viewIndex;
private ItemManagerConfig(final Map<ColumnDef, ItemColumnConfig> cols0, boolean showUniqueCardsOption0, boolean uniqueCardsOnly0, boolean hideFilters0, GroupDef groupBy0, ColumnDef pileBy0, int imageColumnCount0, int viewIndex0) {
cols = cols0;
for (ItemColumnConfig colConfig : cols.values()) {
colConfig.establishDefaults();
}
showUniqueCardsOption = showUniqueCardsOption0;
uniqueCardsOnly = new Prop<Boolean>(uniqueCardsOnly0);
hideFilters = new Prop<Boolean>(hideFilters0);
compactListView = new Prop<Boolean>(FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_LIST_ITEMS)); //use main setting to determine default
groupBy = new Prop<GroupDef>(groupBy0);
pileBy = new Prop<ColumnDef>(pileBy0);
imageColumnCount = new Prop<Integer>(imageColumnCount0);
viewIndex = new Prop<Integer>(viewIndex0);
}
private class Prop<T> {
private T value;
private T defaultValue;
private Prop(T defaultValue0) {
value = defaultValue0;
defaultValue = defaultValue0;
}
private T getValue() {
return value;
}
private void setValue(T value0) {
if (value == value0) { return; }
value = value0;
save();
}
@SuppressWarnings("rawtypes")
private void writeValue(final Element el, String localName) {
if (value == null) {
if (defaultValue != null) {
el.setAttribute(localName, "");
}
}
else if (!value.equals(defaultValue)) {
if (value instanceof Enum) { //use Enum.name to prevent issues with toString() overrides
el.setAttribute(localName, ((Enum)value).name());
}
else {
el.setAttribute(localName, String.valueOf(value));
}
}
}
}
public Map<ColumnDef, ItemColumnConfig> getCols() {
return cols;
}
public boolean getShowUniqueCardsOption() {
return showUniqueCardsOption;
}
public boolean getUniqueCardsOnly() {
return uniqueCardsOnly.getValue();
}
public void setUniqueCardsOnly(boolean value0) {
uniqueCardsOnly.setValue(value0);
}
public boolean getHideFilters() {
return hideFilters.getValue();
}
public void setHideFilters(boolean value0) {
hideFilters.setValue(value0);
}
public boolean getCompactListView() {
return compactListView.getValue();
}
public void setCompactListView(boolean value0) {
compactListView.setValue(value0);
}
public GroupDef getGroupBy() {
return groupBy.getValue();
}
public void setGroupBy(GroupDef value0) {
groupBy.setValue(value0);
}
public ColumnDef getPileBy() {
return pileBy.getValue();
}
public void setPileBy(ColumnDef value0) {
pileBy.setValue(value0);
}
public int getImageColumnCount() {
return imageColumnCount.getValue();
}
public void setImageColumnCount(int value0) {
imageColumnCount.setValue(value0);
}
public int getViewIndex() {
return viewIndex.getValue();
}
public void setViewIndex(int value0) {
viewIndex.setValue(value0);
}
public static void load() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(new File(ForgeConstants.ITEM_VIEW_PREFS_FILE));
final NodeList configs = document.getElementsByTagName("config");
for (int i = 0; i < configs.getLength(); i++) {
try { //capture enum parse errors without losing other preferences
final Element el = (Element)configs.item(i);
final ItemManagerConfig config = Enum.valueOf(ItemManagerConfig.class, el.getAttribute("name"));
if (el.hasAttribute("uniqueCardsOnly")) {
config.uniqueCardsOnly.value = Boolean.parseBoolean(el.getAttribute("uniqueCardsOnly"));
}
if (el.hasAttribute("hideFilters")) {
config.hideFilters.value = Boolean.parseBoolean(el.getAttribute("hideFilters"));
}
if (el.hasAttribute("compactListView")) {
config.compactListView.value = Boolean.parseBoolean(el.getAttribute("compactListView"));
}
if (el.hasAttribute("groupBy")) {
String value = el.getAttribute("groupBy");
if (value.isEmpty()) {
config.groupBy.value = null;
}
else {
config.groupBy.value = Enum.valueOf(GroupDef.class, value);
}
}
if (el.hasAttribute("pileBy")) {
String value = el.getAttribute("pileBy");
if (value.isEmpty()) {
config.pileBy.value = null;
}
else {
config.pileBy.value = Enum.valueOf(ColumnDef.class, value);
}
}
if (el.hasAttribute("imageColumnCount")) {
config.imageColumnCount.value = Integer.parseInt(el.getAttribute("imageColumnCount"));
}
if (el.hasAttribute("viewIndex")) {
config.viewIndex.value = Integer.parseInt(el.getAttribute("viewIndex"));
}
final NodeList cols = el.getElementsByTagName("col");
for (int j = 0; j < cols.getLength(); j++) {
try { //capture enum parse errors without losing other column preferences
final Element colEl = (Element)cols.item(j);
ItemColumnConfig colConfig = config.cols.get(Enum.valueOf(ColumnDef.class, colEl.getAttribute("name")));
if (colEl.hasAttribute("width")) {
colConfig.setPreferredWidth(Integer.parseInt(colEl.getAttribute("width")));
}
if (colEl.hasAttribute("sortPriority")) {
colConfig.setSortPriority(Integer.parseInt(colEl.getAttribute("sortPriority")));
}
if (colEl.hasAttribute("sortState")) {
colConfig.setSortState(Enum.valueOf(SortState.class, colEl.getAttribute("sortState")));
}
if (colEl.hasAttribute("index")) {
colConfig.setIndex(Integer.parseInt(colEl.getAttribute("index")));
}
if (colEl.hasAttribute("visible")) {
colConfig.setVisible(Boolean.parseBoolean(colEl.getAttribute("visible")));
}
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
catch (FileNotFoundException e) {
//ok if file not found
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void save() {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("preferences");
root.setAttribute("type", "item_view");
document.appendChild(root);
for (ItemManagerConfig config : ItemManagerConfig.values()) {
Element el = document.createElement("config");
el.setAttribute("name", config.name());
config.uniqueCardsOnly.writeValue(el, "uniqueCardsOnly");
config.hideFilters.writeValue(el, "hideFilters");
config.compactListView.writeValue(el, "compactListView");
config.groupBy.writeValue(el, "groupBy");
config.pileBy.writeValue(el, "pileBy");
config.imageColumnCount.writeValue(el, "imageColumnCount");
config.viewIndex.writeValue(el, "viewIndex");
for (ItemColumnConfig colConfig : config.cols.values()) {
Element colEl = document.createElement("col");
colEl.setAttribute("name", colConfig.getDef().name());
if (colConfig.getPreferredWidth() != colConfig.getDefaults().getPreferredWidth()) {
colEl.setAttribute("width", String.valueOf(colConfig.getPreferredWidth()));
}
if (colConfig.getSortPriority() != colConfig.getDefaults().getSortPriority()) {
colEl.setAttribute("sortPriority", String.valueOf(colConfig.getSortPriority()));
}
if (colConfig.getSortState() != colConfig.getDefaults().getSortState()) {
colEl.setAttribute("sortState", String.valueOf(colConfig.getSortState()));
}
if (colConfig.getIndex() != colConfig.getDefaults().getIndex()) {
colEl.setAttribute("index", String.valueOf(colConfig.getIndex()));
}
if (colConfig.isVisible() != colConfig.getDefaults().isVisible()) {
colEl.setAttribute("visible", String.valueOf(colConfig.isVisible()));
}
el.appendChild(colEl);
}
root.appendChild(el);
}
XmlUtil.saveDocument(document, ForgeConstants.ITEM_VIEW_PREFS_FILE);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,232 +1,232 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import forge.item.InventoryItem;
import forge.itemmanager.ItemColumnConfig.SortState;
import forge.util.ItemPool;
import forge.util.ItemPoolSorter;
public final class ItemManagerModel<T extends InventoryItem> {
private static final int maxSortDepth = 3;
private final ItemPool<T> data;
private boolean infiniteSupply;
private final CascadeManager cascadeManager = new CascadeManager();
public ItemManagerModel(final Class<T> genericType0) {
data = new ItemPool<T>(genericType0);
}
public void clear() {
data.clear();
}
// same thing as above, it was copied to provide sorting (needed by table
// views in deck editors)
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
protected transient boolean isListInSync = false;
public List<Entry<T, Integer>> getOrderedList() {
if (!isListInSync) {
rebuildOrderedList();
}
return itemsOrdered;
}
private void rebuildOrderedList() {
itemsOrdered.clear();
if (data != null) {
for (final Entry<T, Integer> e : data) {
itemsOrdered.add(e);
}
}
isListInSync = true;
}
public int countDistinct() {
return data.countDistinct();
}
public ItemPool<T> getItems() {
return data.getView();
}
public void removeItem(final T item0, final int qty) {
if (data.count(item0) > 0) {
if (isInfinite()) {
data.removeAll(item0);
}
else {
data.remove(item0, qty);
}
isListInSync = false;
}
}
public void replaceAll(final T item0, final T replacement0) {
final int count = data.count(item0);
if (count > 0) {
data.removeAll(item0);
data.add(replacement0, count);
isListInSync = false;
}
}
public void addItem(final T item0, final int qty) {
data.add(item0, qty);
isListInSync = false;
}
public void addItems(final Iterable<Entry<T, Integer>> items0) {
data.addAll(items0);
isListInSync = false;
}
/**
* Sets whether this table's pool of items is in infinite supply. If false,
* items in the table have a limited number of copies.
*/
public void setInfinite(final boolean infinite) {
infiniteSupply = infinite;
}
public boolean isInfinite() {
return infiniteSupply;
}
public CascadeManager getCascadeManager() {
return cascadeManager;
}
public void refreshSort() {
if (getOrderedList().isEmpty()) { return; }
Collections.sort(getOrderedList(), new MyComparator());
}
//Manages sorting orders for multiple depths of sorting
public final class CascadeManager {
private final List<ItemColumn> colsToSort = new ArrayList<ItemColumn>(3);
private Sorter sorter = null;
// Adds a column to sort cascade list.
// If column is first in the cascade, inverts direction of sort.
// Otherwise, sorts in ascending direction.
public void add(final ItemColumn col0, final boolean forSetup) {
sorter = null;
if (forSetup) { //just add column unmodified if setting up sort columns
colsToSort.add(0, col0);
}
else {
if (colsToSort.size() > 0 && colsToSort.get(0).equals(col0)) { //if column already at top level, just invert
col0.getConfig().setSortPriority(1);
col0.getConfig().setSortState(col0.getConfig().getSortState() == SortState.ASC ? SortState.DESC : SortState.ASC);
}
else { //otherwise move column to top level and move others down
colsToSort.remove(col0);
col0.getConfig().setSortPriority(1);
col0.getConfig().setSortState(col0.getConfig().getDefaultSortState());
colsToSort.add(0, col0);
}
//decrement sort priority on remaining columns
for (int i = 1; i < maxSortDepth; i++) {
if (colsToSort.size() == i) { break; }
if (colsToSort.get(i).getConfig().getSortPriority() != 0) {
colsToSort.get(i).getConfig().setSortPriority(i + 1);
}
}
}
//unset and remove boundary columns.
if (colsToSort.size() > maxSortDepth) {
colsToSort.get(maxSortDepth).getConfig().setSortPriority(0);
colsToSort.remove(maxSortDepth);
}
}
public Sorter getSorter() {
if (sorter == null) {
sorter = createSorter();
}
return sorter;
}
public void reset() {
colsToSort.clear();
sorter = null;
}
private Sorter createSorter() {
final List<ItemPoolSorter<InventoryItem>> oneColSorters = new ArrayList<ItemPoolSorter<InventoryItem>>(maxSortDepth);
for (final ItemColumn col : colsToSort) {
oneColSorters.add(new ItemPoolSorter<InventoryItem>(
col.getFnSort(),
col.getConfig().getSortState().equals(SortState.ASC) ? true : false));
}
return new Sorter(oneColSorters);
}
public class Sorter implements Comparator<Entry<InventoryItem, Integer>> {
private final List<ItemPoolSorter<InventoryItem>> sorters;
private final int cntFields;
public Sorter(final List<ItemPoolSorter<InventoryItem>> sorters0) {
sorters = sorters0;
cntFields = sorters0.size();
}
@Override
public final int compare(final Entry<InventoryItem, Integer> arg0, final Entry<InventoryItem, Integer> arg1) {
int lastCompare = 0;
int iField = -1;
while ((++iField < cntFields) && (lastCompare == 0)) { // reverse
// iteration
final ItemPoolSorter<InventoryItem> sorter = sorters.get(iField);
if (sorter == null) {
break;
}
lastCompare = sorter.compare(arg0, arg1);
}
return lastCompare;
}
}
}
private final class MyComparator implements Comparator<Entry<T, Integer>> {
@SuppressWarnings("unchecked")
@Override
public int compare(final Entry<T, Integer> o1, final Entry<T, Integer> o2) {
return cascadeManager.getSorter().compare((Entry<InventoryItem, Integer>)o1, (Entry<InventoryItem, Integer>)o2);
}
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import forge.item.InventoryItem;
import forge.itemmanager.ItemColumnConfig.SortState;
import forge.util.ItemPool;
import forge.util.ItemPoolSorter;
public final class ItemManagerModel<T extends InventoryItem> {
private static final int maxSortDepth = 3;
private final ItemPool<T> data;
private boolean infiniteSupply;
private final CascadeManager cascadeManager = new CascadeManager();
public ItemManagerModel(final Class<T> genericType0) {
data = new ItemPool<T>(genericType0);
}
public void clear() {
data.clear();
}
// same thing as above, it was copied to provide sorting (needed by table
// views in deck editors)
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
protected transient boolean isListInSync = false;
public List<Entry<T, Integer>> getOrderedList() {
if (!isListInSync) {
rebuildOrderedList();
}
return itemsOrdered;
}
private void rebuildOrderedList() {
itemsOrdered.clear();
if (data != null) {
for (final Entry<T, Integer> e : data) {
itemsOrdered.add(e);
}
}
isListInSync = true;
}
public int countDistinct() {
return data.countDistinct();
}
public ItemPool<T> getItems() {
return data.getView();
}
public void removeItem(final T item0, final int qty) {
if (data.count(item0) > 0) {
if (isInfinite()) {
data.removeAll(item0);
}
else {
data.remove(item0, qty);
}
isListInSync = false;
}
}
public void replaceAll(final T item0, final T replacement0) {
final int count = data.count(item0);
if (count > 0) {
data.removeAll(item0);
data.add(replacement0, count);
isListInSync = false;
}
}
public void addItem(final T item0, final int qty) {
data.add(item0, qty);
isListInSync = false;
}
public void addItems(final Iterable<Entry<T, Integer>> items0) {
data.addAll(items0);
isListInSync = false;
}
/**
* Sets whether this table's pool of items is in infinite supply. If false,
* items in the table have a limited number of copies.
*/
public void setInfinite(final boolean infinite) {
infiniteSupply = infinite;
}
public boolean isInfinite() {
return infiniteSupply;
}
public CascadeManager getCascadeManager() {
return cascadeManager;
}
public void refreshSort() {
if (getOrderedList().isEmpty()) { return; }
Collections.sort(getOrderedList(), new MyComparator());
}
//Manages sorting orders for multiple depths of sorting
public final class CascadeManager {
private final List<ItemColumn> colsToSort = new ArrayList<ItemColumn>(3);
private Sorter sorter = null;
// Adds a column to sort cascade list.
// If column is first in the cascade, inverts direction of sort.
// Otherwise, sorts in ascending direction.
public void add(final ItemColumn col0, final boolean forSetup) {
sorter = null;
if (forSetup) { //just add column unmodified if setting up sort columns
colsToSort.add(0, col0);
}
else {
if (colsToSort.size() > 0 && colsToSort.get(0).equals(col0)) { //if column already at top level, just invert
col0.getConfig().setSortPriority(1);
col0.getConfig().setSortState(col0.getConfig().getSortState() == SortState.ASC ? SortState.DESC : SortState.ASC);
}
else { //otherwise move column to top level and move others down
colsToSort.remove(col0);
col0.getConfig().setSortPriority(1);
col0.getConfig().setSortState(col0.getConfig().getDefaultSortState());
colsToSort.add(0, col0);
}
//decrement sort priority on remaining columns
for (int i = 1; i < maxSortDepth; i++) {
if (colsToSort.size() == i) { break; }
if (colsToSort.get(i).getConfig().getSortPriority() != 0) {
colsToSort.get(i).getConfig().setSortPriority(i + 1);
}
}
}
//unset and remove boundary columns.
if (colsToSort.size() > maxSortDepth) {
colsToSort.get(maxSortDepth).getConfig().setSortPriority(0);
colsToSort.remove(maxSortDepth);
}
}
public Sorter getSorter() {
if (sorter == null) {
sorter = createSorter();
}
return sorter;
}
public void reset() {
colsToSort.clear();
sorter = null;
}
private Sorter createSorter() {
final List<ItemPoolSorter<InventoryItem>> oneColSorters = new ArrayList<ItemPoolSorter<InventoryItem>>(maxSortDepth);
for (final ItemColumn col : colsToSort) {
oneColSorters.add(new ItemPoolSorter<InventoryItem>(
col.getFnSort(),
col.getConfig().getSortState().equals(SortState.ASC) ? true : false));
}
return new Sorter(oneColSorters);
}
public class Sorter implements Comparator<Entry<InventoryItem, Integer>> {
private final List<ItemPoolSorter<InventoryItem>> sorters;
private final int cntFields;
public Sorter(final List<ItemPoolSorter<InventoryItem>> sorters0) {
sorters = sorters0;
cntFields = sorters0.size();
}
@Override
public final int compare(final Entry<InventoryItem, Integer> arg0, final Entry<InventoryItem, Integer> arg1) {
int lastCompare = 0;
int iField = -1;
while ((++iField < cntFields) && (lastCompare == 0)) { // reverse
// iteration
final ItemPoolSorter<InventoryItem> sorter = sorters.get(iField);
if (sorter == null) {
break;
}
lastCompare = sorter.compare(arg0, arg1);
}
return lastCompare;
}
}
}
private final class MyComparator implements Comparator<Entry<T, Integer>> {
@SuppressWarnings("unchecked")
@Override
public int compare(final Entry<T, Integer> o1, final Entry<T, Integer> o2) {
return cascadeManager.getSorter().compare((Entry<InventoryItem, Integer>)o1, (Entry<InventoryItem, Integer>)o2);
}
}
}

View File

@@ -1,234 +1,234 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.itemmanager.ItemColumnConfig.SortState;
/**
* A collection of methods pertaining to columns in card catalog and
* current deck tables, for use in the deck editor.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SColumnUtil {
public static Map<ColumnDef, ItemColumnConfig> getColumns(Iterable<ColumnDef> colDefs) {
int i = 0;
final Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
for (ColumnDef colDef : colDefs) {
ItemColumnConfig column = new ItemColumnConfig(colDef);
column.setIndex(i++);
columns.put(colDef, column);
}
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getStringColumn() {
Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
ItemColumnConfig column = new ItemColumnConfig(ColumnDef.STRING);
column.setSortPriority(1);
columns.put(ColumnDef.STRING, column);
return columns;
}
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite) {
return getCardColumns(quantityColDef, includeFavorite, false, false, false, false);
}
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite,
boolean includeOwned, boolean includePrice, boolean includeNew, boolean includeDecks) {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
if (includeFavorite) {
colDefs.add(ColumnDef.FAVORITE);
}
if (quantityColDef != null) {
colDefs.add(quantityColDef);
}
if (includeOwned) {
colDefs.add(ColumnDef.OWNED);
}
colDefs.add(ColumnDef.NAME);
if (includePrice) {
colDefs.add(ColumnDef.PRICE);
}
if (includeNew) {
colDefs.add(ColumnDef.NEW);
}
if (includeDecks) {
colDefs.add(ColumnDef.DECKS);
}
colDefs.add(ColumnDef.COST);
colDefs.add(ColumnDef.COLOR);
colDefs.add(ColumnDef.TYPE);
colDefs.add(ColumnDef.POWER);
colDefs.add(ColumnDef.TOUGHNESS);
colDefs.add(ColumnDef.CMC);
colDefs.add(ColumnDef.RARITY);
colDefs.add(ColumnDef.SET);
colDefs.add(ColumnDef.AI);
colDefs.add(ColumnDef.RANKING);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.AI).setVisible(false);
columns.get(ColumnDef.RANKING).setVisible(false);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getCatalogDefaultColumns(boolean isInfinite) {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(isInfinite ? null : ColumnDef.QUANTITY, true);
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDeckViewerDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDraftPackDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
columns.get(ColumnDef.RARITY).setSortPriority(1); //sort rares to top
columns.get(ColumnDef.RARITY).setSortState(SortState.DESC);
columns.get(ColumnDef.COLOR).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
columns.get(ColumnDef.RANKING).setVisible(true);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getSpecialCardPoolDefaultColumns() {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.FAVORITE);
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.TYPE);
colDefs.add(ColumnDef.RARITY);
colDefs.add(ColumnDef.SET);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getSpellShopDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, true, true, false, false);
columns.get(ColumnDef.OWNED).setSortPriority(1);
columns.get(ColumnDef.PRICE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestInventoryDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, true, true, true);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.PRICE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestEditorPoolDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, false, true, false);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, true);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestAEtherDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, false, false);
columns.get(ColumnDef.NAME).setSortPriority(1);
columns.get(ColumnDef.COLOR).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestCollectionDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, true, false);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestCommandersDefaultColumns() {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.COLOR);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.NAME).setSortPriority(1);
columns.get(ColumnDef.COLOR).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDecksDefaultColumns(boolean allowEdit, boolean includeFolder) {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.DECK_FAVORITE);
if (allowEdit) {
colDefs.add(ColumnDef.DECK_ACTIONS);
}
if (includeFolder) {
colDefs.add(ColumnDef.DECK_FOLDER);
}
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.DECK_COLOR);
colDefs.add(ColumnDef.DECK_FORMAT);
colDefs.add(ColumnDef.DECK_EDITION);
colDefs.add(ColumnDef.DECK_MAIN);
colDefs.add(ColumnDef.DECK_SIDE);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.DECK_FAVORITE).setSortPriority(1);
if (includeFolder) {
columns.get(ColumnDef.DECK_FOLDER).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
}
else {
columns.get(ColumnDef.NAME).setSortPriority(2);
}
return columns;
}
}
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.itemmanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.itemmanager.ItemColumnConfig.SortState;
/**
* A collection of methods pertaining to columns in card catalog and
* current deck tables, for use in the deck editor.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SColumnUtil {
public static Map<ColumnDef, ItemColumnConfig> getColumns(Iterable<ColumnDef> colDefs) {
int i = 0;
final Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
for (ColumnDef colDef : colDefs) {
ItemColumnConfig column = new ItemColumnConfig(colDef);
column.setIndex(i++);
columns.put(colDef, column);
}
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getStringColumn() {
Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
ItemColumnConfig column = new ItemColumnConfig(ColumnDef.STRING);
column.setSortPriority(1);
columns.put(ColumnDef.STRING, column);
return columns;
}
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite) {
return getCardColumns(quantityColDef, includeFavorite, false, false, false, false);
}
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite,
boolean includeOwned, boolean includePrice, boolean includeNew, boolean includeDecks) {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
if (includeFavorite) {
colDefs.add(ColumnDef.FAVORITE);
}
if (quantityColDef != null) {
colDefs.add(quantityColDef);
}
if (includeOwned) {
colDefs.add(ColumnDef.OWNED);
}
colDefs.add(ColumnDef.NAME);
if (includePrice) {
colDefs.add(ColumnDef.PRICE);
}
if (includeNew) {
colDefs.add(ColumnDef.NEW);
}
if (includeDecks) {
colDefs.add(ColumnDef.DECKS);
}
colDefs.add(ColumnDef.COST);
colDefs.add(ColumnDef.COLOR);
colDefs.add(ColumnDef.TYPE);
colDefs.add(ColumnDef.POWER);
colDefs.add(ColumnDef.TOUGHNESS);
colDefs.add(ColumnDef.CMC);
colDefs.add(ColumnDef.RARITY);
colDefs.add(ColumnDef.SET);
colDefs.add(ColumnDef.AI);
colDefs.add(ColumnDef.RANKING);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.AI).setVisible(false);
columns.get(ColumnDef.RANKING).setVisible(false);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getCatalogDefaultColumns(boolean isInfinite) {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(isInfinite ? null : ColumnDef.QUANTITY, true);
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDeckViewerDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDraftPackDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
columns.get(ColumnDef.RARITY).setSortPriority(1); //sort rares to top
columns.get(ColumnDef.RARITY).setSortState(SortState.DESC);
columns.get(ColumnDef.COLOR).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
columns.get(ColumnDef.RANKING).setVisible(true);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getSpecialCardPoolDefaultColumns() {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.FAVORITE);
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.TYPE);
colDefs.add(ColumnDef.RARITY);
colDefs.add(ColumnDef.SET);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getSpellShopDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, true, true, false, false);
columns.get(ColumnDef.OWNED).setSortPriority(1);
columns.get(ColumnDef.PRICE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestInventoryDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, true, true, true);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.PRICE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestEditorPoolDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, false, true, false);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getQuestDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, true);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestAEtherDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, false, false);
columns.get(ColumnDef.NAME).setSortPriority(1);
columns.get(ColumnDef.COLOR).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestCollectionDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, true, false);
columns.get(ColumnDef.NEW).setSortPriority(1);
columns.get(ColumnDef.NAME).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestDeckEditorDefaultColumns() {
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, false);
columns.get(ColumnDef.CMC).setSortPriority(1);
columns.get(ColumnDef.TYPE).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getConquestCommandersDefaultColumns() {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.COLOR);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.NAME).setSortPriority(1);
columns.get(ColumnDef.COLOR).setSortPriority(2);
return columns;
}
public static Map<ColumnDef, ItemColumnConfig> getDecksDefaultColumns(boolean allowEdit, boolean includeFolder) {
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
colDefs.add(ColumnDef.DECK_FAVORITE);
if (allowEdit) {
colDefs.add(ColumnDef.DECK_ACTIONS);
}
if (includeFolder) {
colDefs.add(ColumnDef.DECK_FOLDER);
}
colDefs.add(ColumnDef.NAME);
colDefs.add(ColumnDef.DECK_COLOR);
colDefs.add(ColumnDef.DECK_FORMAT);
colDefs.add(ColumnDef.DECK_EDITION);
colDefs.add(ColumnDef.DECK_MAIN);
colDefs.add(ColumnDef.DECK_SIDE);
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
columns.get(ColumnDef.DECK_FAVORITE).setSortPriority(1);
if (includeFolder) {
columns.get(ColumnDef.DECK_FOLDER).setSortPriority(2);
columns.get(ColumnDef.NAME).setSortPriority(3);
}
else {
columns.get(ColumnDef.NAME).setSortPriority(2);
}
return columns;
}
}

View File

@@ -1,394 +1,394 @@
package forge.itemmanager;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.StaticData;
import forge.card.*;
import forge.deck.DeckProxy;
import forge.game.GameFormat;
import forge.interfaces.IButton;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.itemmanager.SItemManagerUtil.StatTypes;
import forge.model.FModel;
import forge.properties.ForgePreferences;
import forge.quest.data.StarRating;
import forge.util.BinaryUtil;
import forge.util.PredicateString.StringOp;
import java.util.*;
/**
* Static factory; holds blocks of form elements and predicates
* which are used in various editing environments.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*/
public class SFilterUtil {
/**
* builds a string search filter
*/
public static Predicate<PaperCard> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText, boolean inCost) {
text = text.trim();
if (text.isEmpty()) {
return Predicates.alwaysTrue();
}
if (BooleanExpression.isExpression(text)) {
BooleanExpression expression = new BooleanExpression(text, inName, inType, inText, inCost);
try {
Predicate<CardRules> filter = expression.evaluate();
if (filter != null) {
return Predicates.compose(invert ? Predicates.not(filter) : filter, PaperCard.FN_GET_RULES);
}
}
catch (Exception ignored) {
ignored.printStackTrace();
//Continue with standard filtering if the expression is not valid.
}
}
List<String> splitText = getSplitText(text);
List<Predicate<CardRules>> terms = new ArrayList<>();
for (String s : splitText) {
List<Predicate<CardRules>> subands = new ArrayList<>();
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, s)); }
if (inCost) { subands.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, s)); }
terms.add(Predicates.or(subands));
}
Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
return Predicates.compose(textFilter, PaperCard.FN_GET_RULES);
}
private static List<String> getSplitText(String text) {
boolean inQuotes = false;
String entry = "";
List<String> splitText = new ArrayList<String>();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case ' ':
if (!inQuotes) { //if not in quotes, end current entry
if (entry.length() > 0) {
splitText.add(entry);
entry = "";
}
continue;
}
break;
case '"':
inQuotes = !inQuotes;
continue; //don't append quotation character itself
case '\\':
if (i < text.length() - 1 && text.charAt(i + 1) == '"') {
ch = '"'; //allow appending escaped quotation character
i++; //prevent changing inQuotes for that character
}
break;
case ',':
if (!inQuotes) { //ignore commas outside quotes
continue;
}
break;
}
entry += ch;
}
if (entry.length() > 0) {
splitText.add(entry);
}
return splitText;
}
public static <T extends InventoryItem> Predicate<T> buildItemTextFilter(String text) {
if (text.trim().isEmpty()) {
return Predicates.alwaysTrue();
}
return new ItemTextPredicate<>(text);
}
private static class ItemTextPredicate<T extends InventoryItem> implements Predicate<T> {
private final List<String> splitText;
private ItemTextPredicate(String text) {
splitText = getSplitText(text.toLowerCase());
}
@Override
public boolean apply(T input) {
String name = input.getName().toLowerCase();
for (String s : splitText) {
if (name.contains(s)) {
return true;
}
}
return false;
}
}
public static Predicate<PaperCard> buildStarRatingFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap, final HashSet<StarRating> QuestRatings) {
final Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap2 = buttonMap;
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
StarRating r = new StarRating();
r.Name = card.getName();
r.Edition = card.getEdition();
int j = 0;
for (int i = 1; i < 6; i++) {
r.rating = i;
if (QuestRatings.contains(r)) {
j = i;
}
}
boolean result = true;
if (j == 0) {
if (!buttonMap2.get(StatTypes.RATE_NONE).isSelected()) {
result = false;
}
} else if (j == 1) {
if (!buttonMap2.get(StatTypes.RATE_1).isSelected()) {
result = false;
}
} else if (j == 2) {
if (!buttonMap2.get(StatTypes.RATE_2).isSelected()) {
result = false;
}
} else if (j == 3) {
if (!buttonMap2.get(StatTypes.RATE_3).isSelected()) {
result = false;
}
} else if (j == 4) {
if (!buttonMap2.get(StatTypes.RATE_4).isSelected()) {
result = false;
}
} else if (j == 5) {
if (!buttonMap2.get(StatTypes.RATE_5).isSelected()) {
result = false;
}
}
return result;
}
};
}
public static Predicate<PaperCard> buildFoilFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
final int Foil = (((buttonMap.get(StatTypes.FOIL_OLD).isSelected()) ? 1 : 0)
+ ((buttonMap.get(StatTypes.FOIL_NEW).isSelected()) ? 2 : 0)
+ ((buttonMap.get(StatTypes.FOIL_NONE).isSelected()) ? 4 : 0));
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
boolean result = false;
CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
if ((Foil & 1) == 1) {
// Old Style Foil
if (edition.getFoilType() == CardEdition.FoilType.OLD_STYLE) {
result = result || card.isFoil();
}
}
if ((Foil & 2) == 2) {
// New Style Foil
if (edition.getFoilType() == CardEdition.FoilType.MODERN) {
result = result || card.isFoil();
}
}
if ((Foil & 4) == 4) {
result = result || !card.isFoil();
}
return result;
}
};
}
public static Predicate<PaperCard> buildColorFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
byte colors0 = 0;
if (buttonMap.get(StatTypes.WHITE).isSelected()) {
colors0 |= MagicColor.WHITE;
}
if (buttonMap.get(StatTypes.BLUE).isSelected()) {
colors0 |= MagicColor.BLUE;
}
if (buttonMap.get(StatTypes.BLACK).isSelected()) {
colors0 |= MagicColor.BLACK;
}
if (buttonMap.get(StatTypes.RED).isSelected()) {
colors0 |= MagicColor.RED;
}
if (buttonMap.get(StatTypes.GREEN).isSelected()) {
colors0 |= MagicColor.GREEN;
}
final byte colors = colors0;
final boolean wantColorless = buttonMap.get(StatTypes.COLORLESS).isSelected();
final boolean wantMulticolor = buttonMap.get(StatTypes.MULTICOLOR).isSelected();
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
CardRules rules = card.getRules();
ColorSet color = rules.getColor();
boolean allColorsFilteredOut = colors == 0;
//use color identity for lands, which allows filtering to just lands that can be played in your deck
boolean useColorIdentity = rules.getType().isLand() && !allColorsFilteredOut && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY);
if (useColorIdentity) {
color = rules.getColorIdentity();
}
boolean result = true;
if (wantMulticolor) {
if (colors == 0) { //handle showing all multi-color cards if all 5 colors are filtered
result = color.isMulticolor() || (wantColorless && color.isColorless());
} else if (colors != ColorSet.ALL_COLORS.getColor()) {
if (useColorIdentity && !allColorsFilteredOut) {
result = color.hasAnyColor(colors) || (wantColorless && color.isColorless());
} else {
result = (wantColorless && color.isColorless()) || rules.canCastWithAvailable(colors);
}
}
} else {
result = !color.isMulticolor();
if (colors != ColorSet.ALL_COLORS.getColor()) {
if (useColorIdentity && !allColorsFilteredOut) {
result = result && (color.hasAnyColor(colors) || (wantColorless && color.isColorless()));
} else {
result = result && (color.isColorless() || rules.canCastWithAvailable(colors));
}
}
}
if (!wantColorless) {
if (colors != 0 && colors != ColorSet.ALL_COLORS.getColor()) {
//if colorless filtered out ensure phyrexian cards don't appear
//unless at least one of their colors is selected
result = result && color.hasAnyColor(colors);
}
result = result && !color.isColorless();
}
return result;
}
};
}
public static Predicate<DeckProxy> buildDeckColorFilter(final Map<StatTypes, ? extends IButton> buttonMap) {
return new Predicate<DeckProxy>() {
@Override
public boolean apply(DeckProxy input) {
byte colorProfile = input.getColor().getColor();
if (colorProfile == 0) {
return buttonMap.get(StatTypes.DECK_COLORLESS).isSelected();
}
boolean wantMulticolor = buttonMap.get(StatTypes.DECK_MULTICOLOR).isSelected();
if (!wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1) {
return false;
}
byte colors = 0;
if (buttonMap.get(StatTypes.DECK_WHITE).isSelected()) {
colors |= MagicColor.WHITE;
}
if (buttonMap.get(StatTypes.DECK_BLUE).isSelected()) {
colors |= MagicColor.BLUE;
}
if (buttonMap.get(StatTypes.DECK_BLACK).isSelected()) {
colors |= MagicColor.BLACK;
}
if (buttonMap.get(StatTypes.DECK_RED).isSelected()) {
colors |= MagicColor.RED;
}
if (buttonMap.get(StatTypes.DECK_GREEN).isSelected()) {
colors |= MagicColor.GREEN;
}
return colors == 0 && wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1 || (colorProfile & colors) == colorProfile;
}
};
}
public static void showOnlyStat(StatTypes clickedStat, IButton clickedButton, Map<StatTypes, ? extends IButton> buttonMap) {
boolean foundSelected = false;
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
if (btn.getKey() != clickedStat) {
if (btn.getKey() == StatTypes.MULTICOLOR) {
switch (clickedStat) {
case WHITE:
case BLUE:
case BLACK:
case RED:
case GREEN:
//ensure multicolor filter selected after right-clicking a color filter
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
continue;
default:
break;
}
}
else if (btn.getKey() == StatTypes.DECK_MULTICOLOR) {
switch (clickedStat) {
case DECK_WHITE:
case DECK_BLUE:
case DECK_BLACK:
case DECK_RED:
case DECK_GREEN:
//ensure multicolor filter selected after right-clicking a color filter
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
continue;
default:
break;
}
}
if (btn.getValue().isSelected()) {
foundSelected = true;
btn.getValue().setSelected(false);
}
}
}
if (!clickedButton.isSelected()) {
clickedButton.setSelected(true);
}
else if (!foundSelected) {
//if statLabel only label in group selected, re-select all other labels in group
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
if (btn.getKey() != clickedStat) {
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
}
}
}
}
public static Predicate<PaperCard> buildFormatFilter(Set<GameFormat> formats, boolean allowReprints) {
List<Predicate<PaperCard>> predicates = new ArrayList<>();
for (GameFormat f : formats) {
predicates.add(allowReprints ? f.getFilterRules() : f.getFilterPrinted());
}
return Predicates.or(predicates);
}
public static <T> Predicate<T> optimizedAnd(Predicate<T> p1, Predicate<T> p2) {
return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2));
}
}
package forge.itemmanager;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.StaticData;
import forge.card.*;
import forge.deck.DeckProxy;
import forge.game.GameFormat;
import forge.interfaces.IButton;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.itemmanager.SItemManagerUtil.StatTypes;
import forge.model.FModel;
import forge.properties.ForgePreferences;
import forge.quest.data.StarRating;
import forge.util.BinaryUtil;
import forge.util.PredicateString.StringOp;
import java.util.*;
/**
* Static factory; holds blocks of form elements and predicates
* which are used in various editing environments.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*/
public class SFilterUtil {
/**
* builds a string search filter
*/
public static Predicate<PaperCard> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText, boolean inCost) {
text = text.trim();
if (text.isEmpty()) {
return Predicates.alwaysTrue();
}
if (BooleanExpression.isExpression(text)) {
BooleanExpression expression = new BooleanExpression(text, inName, inType, inText, inCost);
try {
Predicate<CardRules> filter = expression.evaluate();
if (filter != null) {
return Predicates.compose(invert ? Predicates.not(filter) : filter, PaperCard.FN_GET_RULES);
}
}
catch (Exception ignored) {
ignored.printStackTrace();
//Continue with standard filtering if the expression is not valid.
}
}
List<String> splitText = getSplitText(text);
List<Predicate<CardRules>> terms = new ArrayList<>();
for (String s : splitText) {
List<Predicate<CardRules>> subands = new ArrayList<>();
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, s)); }
if (inCost) { subands.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, s)); }
terms.add(Predicates.or(subands));
}
Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
return Predicates.compose(textFilter, PaperCard.FN_GET_RULES);
}
private static List<String> getSplitText(String text) {
boolean inQuotes = false;
String entry = "";
List<String> splitText = new ArrayList<String>();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case ' ':
if (!inQuotes) { //if not in quotes, end current entry
if (entry.length() > 0) {
splitText.add(entry);
entry = "";
}
continue;
}
break;
case '"':
inQuotes = !inQuotes;
continue; //don't append quotation character itself
case '\\':
if (i < text.length() - 1 && text.charAt(i + 1) == '"') {
ch = '"'; //allow appending escaped quotation character
i++; //prevent changing inQuotes for that character
}
break;
case ',':
if (!inQuotes) { //ignore commas outside quotes
continue;
}
break;
}
entry += ch;
}
if (entry.length() > 0) {
splitText.add(entry);
}
return splitText;
}
public static <T extends InventoryItem> Predicate<T> buildItemTextFilter(String text) {
if (text.trim().isEmpty()) {
return Predicates.alwaysTrue();
}
return new ItemTextPredicate<>(text);
}
private static class ItemTextPredicate<T extends InventoryItem> implements Predicate<T> {
private final List<String> splitText;
private ItemTextPredicate(String text) {
splitText = getSplitText(text.toLowerCase());
}
@Override
public boolean apply(T input) {
String name = input.getName().toLowerCase();
for (String s : splitText) {
if (name.contains(s)) {
return true;
}
}
return false;
}
}
public static Predicate<PaperCard> buildStarRatingFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap, final HashSet<StarRating> QuestRatings) {
final Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap2 = buttonMap;
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
StarRating r = new StarRating();
r.Name = card.getName();
r.Edition = card.getEdition();
int j = 0;
for (int i = 1; i < 6; i++) {
r.rating = i;
if (QuestRatings.contains(r)) {
j = i;
}
}
boolean result = true;
if (j == 0) {
if (!buttonMap2.get(StatTypes.RATE_NONE).isSelected()) {
result = false;
}
} else if (j == 1) {
if (!buttonMap2.get(StatTypes.RATE_1).isSelected()) {
result = false;
}
} else if (j == 2) {
if (!buttonMap2.get(StatTypes.RATE_2).isSelected()) {
result = false;
}
} else if (j == 3) {
if (!buttonMap2.get(StatTypes.RATE_3).isSelected()) {
result = false;
}
} else if (j == 4) {
if (!buttonMap2.get(StatTypes.RATE_4).isSelected()) {
result = false;
}
} else if (j == 5) {
if (!buttonMap2.get(StatTypes.RATE_5).isSelected()) {
result = false;
}
}
return result;
}
};
}
public static Predicate<PaperCard> buildFoilFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
final int Foil = (((buttonMap.get(StatTypes.FOIL_OLD).isSelected()) ? 1 : 0)
+ ((buttonMap.get(StatTypes.FOIL_NEW).isSelected()) ? 2 : 0)
+ ((buttonMap.get(StatTypes.FOIL_NONE).isSelected()) ? 4 : 0));
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
boolean result = false;
CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
if ((Foil & 1) == 1) {
// Old Style Foil
if (edition.getFoilType() == CardEdition.FoilType.OLD_STYLE) {
result = result || card.isFoil();
}
}
if ((Foil & 2) == 2) {
// New Style Foil
if (edition.getFoilType() == CardEdition.FoilType.MODERN) {
result = result || card.isFoil();
}
}
if ((Foil & 4) == 4) {
result = result || !card.isFoil();
}
return result;
}
};
}
public static Predicate<PaperCard> buildColorFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
byte colors0 = 0;
if (buttonMap.get(StatTypes.WHITE).isSelected()) {
colors0 |= MagicColor.WHITE;
}
if (buttonMap.get(StatTypes.BLUE).isSelected()) {
colors0 |= MagicColor.BLUE;
}
if (buttonMap.get(StatTypes.BLACK).isSelected()) {
colors0 |= MagicColor.BLACK;
}
if (buttonMap.get(StatTypes.RED).isSelected()) {
colors0 |= MagicColor.RED;
}
if (buttonMap.get(StatTypes.GREEN).isSelected()) {
colors0 |= MagicColor.GREEN;
}
final byte colors = colors0;
final boolean wantColorless = buttonMap.get(StatTypes.COLORLESS).isSelected();
final boolean wantMulticolor = buttonMap.get(StatTypes.MULTICOLOR).isSelected();
return new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
CardRules rules = card.getRules();
ColorSet color = rules.getColor();
boolean allColorsFilteredOut = colors == 0;
//use color identity for lands, which allows filtering to just lands that can be played in your deck
boolean useColorIdentity = rules.getType().isLand() && !allColorsFilteredOut && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY);
if (useColorIdentity) {
color = rules.getColorIdentity();
}
boolean result = true;
if (wantMulticolor) {
if (colors == 0) { //handle showing all multi-color cards if all 5 colors are filtered
result = color.isMulticolor() || (wantColorless && color.isColorless());
} else if (colors != ColorSet.ALL_COLORS.getColor()) {
if (useColorIdentity && !allColorsFilteredOut) {
result = color.hasAnyColor(colors) || (wantColorless && color.isColorless());
} else {
result = (wantColorless && color.isColorless()) || rules.canCastWithAvailable(colors);
}
}
} else {
result = !color.isMulticolor();
if (colors != ColorSet.ALL_COLORS.getColor()) {
if (useColorIdentity && !allColorsFilteredOut) {
result = result && (color.hasAnyColor(colors) || (wantColorless && color.isColorless()));
} else {
result = result && (color.isColorless() || rules.canCastWithAvailable(colors));
}
}
}
if (!wantColorless) {
if (colors != 0 && colors != ColorSet.ALL_COLORS.getColor()) {
//if colorless filtered out ensure phyrexian cards don't appear
//unless at least one of their colors is selected
result = result && color.hasAnyColor(colors);
}
result = result && !color.isColorless();
}
return result;
}
};
}
public static Predicate<DeckProxy> buildDeckColorFilter(final Map<StatTypes, ? extends IButton> buttonMap) {
return new Predicate<DeckProxy>() {
@Override
public boolean apply(DeckProxy input) {
byte colorProfile = input.getColor().getColor();
if (colorProfile == 0) {
return buttonMap.get(StatTypes.DECK_COLORLESS).isSelected();
}
boolean wantMulticolor = buttonMap.get(StatTypes.DECK_MULTICOLOR).isSelected();
if (!wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1) {
return false;
}
byte colors = 0;
if (buttonMap.get(StatTypes.DECK_WHITE).isSelected()) {
colors |= MagicColor.WHITE;
}
if (buttonMap.get(StatTypes.DECK_BLUE).isSelected()) {
colors |= MagicColor.BLUE;
}
if (buttonMap.get(StatTypes.DECK_BLACK).isSelected()) {
colors |= MagicColor.BLACK;
}
if (buttonMap.get(StatTypes.DECK_RED).isSelected()) {
colors |= MagicColor.RED;
}
if (buttonMap.get(StatTypes.DECK_GREEN).isSelected()) {
colors |= MagicColor.GREEN;
}
return colors == 0 && wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1 || (colorProfile & colors) == colorProfile;
}
};
}
public static void showOnlyStat(StatTypes clickedStat, IButton clickedButton, Map<StatTypes, ? extends IButton> buttonMap) {
boolean foundSelected = false;
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
if (btn.getKey() != clickedStat) {
if (btn.getKey() == StatTypes.MULTICOLOR) {
switch (clickedStat) {
case WHITE:
case BLUE:
case BLACK:
case RED:
case GREEN:
//ensure multicolor filter selected after right-clicking a color filter
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
continue;
default:
break;
}
}
else if (btn.getKey() == StatTypes.DECK_MULTICOLOR) {
switch (clickedStat) {
case DECK_WHITE:
case DECK_BLUE:
case DECK_BLACK:
case DECK_RED:
case DECK_GREEN:
//ensure multicolor filter selected after right-clicking a color filter
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
continue;
default:
break;
}
}
if (btn.getValue().isSelected()) {
foundSelected = true;
btn.getValue().setSelected(false);
}
}
}
if (!clickedButton.isSelected()) {
clickedButton.setSelected(true);
}
else if (!foundSelected) {
//if statLabel only label in group selected, re-select all other labels in group
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
if (btn.getKey() != clickedStat) {
if (!btn.getValue().isSelected()) {
btn.getValue().setSelected(true);
}
}
}
}
}
public static Predicate<PaperCard> buildFormatFilter(Set<GameFormat> formats, boolean allowReprints) {
List<Predicate<PaperCard>> predicates = new ArrayList<>();
for (GameFormat f : formats) {
predicates.add(allowReprints ? f.getFilterRules() : f.getFilterPrinted());
}
return Predicates.or(predicates);
}
public static <T> Predicate<T> optimizedAnd(Predicate<T> p1, Predicate<T> p2) {
return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2));
}
}

View File

@@ -1,180 +1,180 @@
package forge.itemmanager;
import com.google.common.base.Predicate;
import forge.assets.FSkinProp;
import forge.assets.IHasSkinProp;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.deck.DeckProxy;
import forge.interfaces.IComboBox;
import forge.item.InventoryItem;
import forge.util.ComparableOp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
/**
* Static methods for working with top-level editor methods,
* included but not limited to preferences IO, icon generation,
* and stats analysis.
*
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SItemManagerUtil {
/** An enum to encapsulate metadata for the stats/filter objects. */
public static enum StatTypes implements IHasSkinProp {
WHITE (FSkinProp.IMG_MANA_W, CardRulesPredicates.Presets.IS_WHITE, "White cards"),
BLUE (FSkinProp.IMG_MANA_U, CardRulesPredicates.Presets.IS_BLUE, "Blue cards"),
BLACK (FSkinProp.IMG_MANA_B, CardRulesPredicates.Presets.IS_BLACK, "Black cards"),
RED (FSkinProp.IMG_MANA_R, CardRulesPredicates.Presets.IS_RED, "Red cards"),
GREEN (FSkinProp.IMG_MANA_G, CardRulesPredicates.Presets.IS_GREEN, "Green cards"),
COLORLESS (FSkinProp.IMG_MANA_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, "Colorless cards"),
MULTICOLOR (FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "Multicolor cards"),
PACK_OR_DECK (FSkinProp.IMG_PACK, null, "Card packs and prebuilt decks"),
LAND (FSkinProp.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, "Lands"),
ARTIFACT (FSkinProp.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT, "Artifacts"),
CREATURE (FSkinProp.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE, "Creatures"),
ENCHANTMENT (FSkinProp.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT, "Enchantments"),
PLANESWALKER (FSkinProp.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER, "Planeswalkers"),
INSTANT (FSkinProp.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT, "Instants"),
SORCERY (FSkinProp.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY, "Sorceries"),
CMC_0 (FSkinProp.IMG_MANA_0, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 0), "Cards with CMC 0"),
CMC_1 (FSkinProp.IMG_MANA_1, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 1), "Cards with CMC 1"),
CMC_2 (FSkinProp.IMG_MANA_2, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 2), "Cards with CMC 2"),
CMC_3 (FSkinProp.IMG_MANA_3, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 3), "Cards with CMC 3"),
CMC_4 (FSkinProp.IMG_MANA_4, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 4), "Cards with CMC 4"),
CMC_5 (FSkinProp.IMG_MANA_5, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 5), "Cards with CMC 5"),
CMC_6 (FSkinProp.IMG_MANA_6, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.GT_OR_EQUAL, 6), "Cards with CMC 6+"),
DECK_WHITE (FSkinProp.IMG_MANA_W, null, "White decks"),
DECK_BLUE (FSkinProp.IMG_MANA_U, null, "Blue decks"),
DECK_BLACK (FSkinProp.IMG_MANA_B, null, "Black decks"),
DECK_RED (FSkinProp.IMG_MANA_R, null, "Red decks"),
DECK_GREEN (FSkinProp.IMG_MANA_G, null, "Green decks"),
DECK_COLORLESS (FSkinProp.IMG_MANA_COLORLESS, null, "Colorless decks"),
DECK_MULTICOLOR (FSkinProp.IMG_MULTI, null, "Multicolor decks"),
FOIL_OLD (FSkinProp.FOIL_11, null, "Old style Foil cards"),
FOIL_NEW (FSkinProp.FOIL_01, null, "New style Foil cards"),
FOIL_NONE (FSkinProp.ICO_CLOSE, null, "Non-Foil cards"),
RATE_NONE (FSkinProp.IMG_FAVNONE, null, "Unrated cards"),
RATE_1 (FSkinProp.IMG_FAV1, null, "1 star cards"),
RATE_2 (FSkinProp.IMG_FAV2, null, "2 star cards"),
RATE_3 (FSkinProp.IMG_FAV3, null, "3 star cards"),
RATE_4 (FSkinProp.IMG_FAV4, null, "4 star cards"),
RATE_5 (FSkinProp.IMG_FAV5, null, "5 star cards");
public final FSkinProp skinProp;
public final Predicate<CardRules> predicate;
public final String label;
private StatTypes(final FSkinProp skinProp0, final Predicate<CardRules> predicate0, final String label0) {
skinProp = skinProp0;
predicate = predicate0;
label = label0;
}
@Override
public FSkinProp getSkinProp() {
return skinProp;
}
}
public static String getItemDisplayString(final InventoryItem item, final int qty, final boolean forTitle) {
final List<InventoryItem> items = new ArrayList<InventoryItem>();
items.add(item);
return getItemDisplayString(items, qty, forTitle);
}
public static String getItemDisplayString(final Iterable<? extends InventoryItem> items, final int qty, final boolean forTitle) {
//determine shared type among items
int itemCount = 0;
String sharedType = null;
boolean checkForSharedType = true;
for (final InventoryItem item : items) {
if (checkForSharedType) {
if (sharedType == null) {
sharedType = item.getItemType();
}
else if (!item.getItemType().equals(sharedType)) {
sharedType = null;
checkForSharedType = false;
}
}
itemCount++;
}
if (sharedType == null) {
sharedType = "Item"; //if no shared type, use generic "item"
}
//build display string based on shared type, item count, and quantity of each item
String result;
if (forTitle) { //convert to lowercase if not for title
result = sharedType;
if (itemCount != 1 || qty != 1) {
result += "s";
}
}
else {
result = sharedType.toLowerCase();
if (itemCount != 1) {
result = itemCount + " " + result + "s";
}
if (qty < 0) { //treat negative numbers as unknown quantity
result = "X copies of " + result;
}
else if (qty != 1) {
result = qty + " copies of " + result;
}
}
return result;
}
public static String buildDisplayList(final Iterable<Entry<InventoryItem, Integer>> items) {
final List<Entry<InventoryItem, Integer>> sorted = new ArrayList<Entry<InventoryItem, Integer>>();
for (final Entry<InventoryItem, Integer> itemEntry : items) {
sorted.add(itemEntry);
}
Collections.sort(sorted, new Comparator<Entry<InventoryItem, Integer>>() {
@Override
public int compare(final Entry<InventoryItem, Integer> x, final Entry<InventoryItem, Integer> y) {
return x.getKey().toString().compareTo(y.getKey().toString());
}
});
final StringBuilder builder = new StringBuilder();
for (final Entry<InventoryItem, Integer> itemEntry : sorted) {
builder.append("\n" + itemEntry.getValue() + " * " + itemEntry.getKey().toString());
}
return builder.toString();
}
private static final GroupDef[] CARD_GROUPBY_OPTIONS = { GroupDef.DEFAULT, GroupDef.CARD_TYPE, GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET, GroupDef.CARD_RARITY };
private static final GroupDef[] DECK_GROUPBY_OPTIONS = { GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET };
private static final ColumnDef[] CARD_PILEBY_OPTIONS = { ColumnDef.CMC, ColumnDef.COLOR, ColumnDef.NAME, ColumnDef.COST, ColumnDef.TYPE, ColumnDef.RARITY, ColumnDef.SET };
private static final ColumnDef[] DECK_PILEBY_OPTIONS = { ColumnDef.DECK_COLOR, ColumnDef.DECK_FOLDER, ColumnDef.NAME, ColumnDef.DECK_FORMAT, ColumnDef.DECK_EDITION };
public static void populateImageViewOptions(final IItemManager<?> itemManager, final IComboBox<Object> cbGroupByOptions, final IComboBox<Object> cbPileByOptions) {
final boolean isDeckManager = itemManager.getGenericType().equals(DeckProxy.class);
final GroupDef[] groupByOptions = isDeckManager ? DECK_GROUPBY_OPTIONS : CARD_GROUPBY_OPTIONS;
final ColumnDef[] pileByOptions = isDeckManager ? DECK_PILEBY_OPTIONS : CARD_PILEBY_OPTIONS;
cbGroupByOptions.addItem("(none)");
cbPileByOptions.addItem("(none)");
for (final GroupDef option : groupByOptions) {
cbGroupByOptions.addItem(option);
}
for (final ColumnDef option : pileByOptions) {
cbPileByOptions.addItem(option);
}
cbGroupByOptions.setSelectedIndex(0);
cbPileByOptions.setSelectedIndex(0);
}
}
package forge.itemmanager;
import com.google.common.base.Predicate;
import forge.assets.FSkinProp;
import forge.assets.IHasSkinProp;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.deck.DeckProxy;
import forge.interfaces.IComboBox;
import forge.item.InventoryItem;
import forge.util.ComparableOp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
/**
* Static methods for working with top-level editor methods,
* included but not limited to preferences IO, icon generation,
* and stats analysis.
*
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SItemManagerUtil {
/** An enum to encapsulate metadata for the stats/filter objects. */
public static enum StatTypes implements IHasSkinProp {
WHITE (FSkinProp.IMG_MANA_W, CardRulesPredicates.Presets.IS_WHITE, "White cards"),
BLUE (FSkinProp.IMG_MANA_U, CardRulesPredicates.Presets.IS_BLUE, "Blue cards"),
BLACK (FSkinProp.IMG_MANA_B, CardRulesPredicates.Presets.IS_BLACK, "Black cards"),
RED (FSkinProp.IMG_MANA_R, CardRulesPredicates.Presets.IS_RED, "Red cards"),
GREEN (FSkinProp.IMG_MANA_G, CardRulesPredicates.Presets.IS_GREEN, "Green cards"),
COLORLESS (FSkinProp.IMG_MANA_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, "Colorless cards"),
MULTICOLOR (FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "Multicolor cards"),
PACK_OR_DECK (FSkinProp.IMG_PACK, null, "Card packs and prebuilt decks"),
LAND (FSkinProp.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, "Lands"),
ARTIFACT (FSkinProp.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT, "Artifacts"),
CREATURE (FSkinProp.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE, "Creatures"),
ENCHANTMENT (FSkinProp.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT, "Enchantments"),
PLANESWALKER (FSkinProp.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER, "Planeswalkers"),
INSTANT (FSkinProp.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT, "Instants"),
SORCERY (FSkinProp.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY, "Sorceries"),
CMC_0 (FSkinProp.IMG_MANA_0, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 0), "Cards with CMC 0"),
CMC_1 (FSkinProp.IMG_MANA_1, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 1), "Cards with CMC 1"),
CMC_2 (FSkinProp.IMG_MANA_2, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 2), "Cards with CMC 2"),
CMC_3 (FSkinProp.IMG_MANA_3, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 3), "Cards with CMC 3"),
CMC_4 (FSkinProp.IMG_MANA_4, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 4), "Cards with CMC 4"),
CMC_5 (FSkinProp.IMG_MANA_5, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 5), "Cards with CMC 5"),
CMC_6 (FSkinProp.IMG_MANA_6, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.GT_OR_EQUAL, 6), "Cards with CMC 6+"),
DECK_WHITE (FSkinProp.IMG_MANA_W, null, "White decks"),
DECK_BLUE (FSkinProp.IMG_MANA_U, null, "Blue decks"),
DECK_BLACK (FSkinProp.IMG_MANA_B, null, "Black decks"),
DECK_RED (FSkinProp.IMG_MANA_R, null, "Red decks"),
DECK_GREEN (FSkinProp.IMG_MANA_G, null, "Green decks"),
DECK_COLORLESS (FSkinProp.IMG_MANA_COLORLESS, null, "Colorless decks"),
DECK_MULTICOLOR (FSkinProp.IMG_MULTI, null, "Multicolor decks"),
FOIL_OLD (FSkinProp.FOIL_11, null, "Old style Foil cards"),
FOIL_NEW (FSkinProp.FOIL_01, null, "New style Foil cards"),
FOIL_NONE (FSkinProp.ICO_CLOSE, null, "Non-Foil cards"),
RATE_NONE (FSkinProp.IMG_FAVNONE, null, "Unrated cards"),
RATE_1 (FSkinProp.IMG_FAV1, null, "1 star cards"),
RATE_2 (FSkinProp.IMG_FAV2, null, "2 star cards"),
RATE_3 (FSkinProp.IMG_FAV3, null, "3 star cards"),
RATE_4 (FSkinProp.IMG_FAV4, null, "4 star cards"),
RATE_5 (FSkinProp.IMG_FAV5, null, "5 star cards");
public final FSkinProp skinProp;
public final Predicate<CardRules> predicate;
public final String label;
private StatTypes(final FSkinProp skinProp0, final Predicate<CardRules> predicate0, final String label0) {
skinProp = skinProp0;
predicate = predicate0;
label = label0;
}
@Override
public FSkinProp getSkinProp() {
return skinProp;
}
}
public static String getItemDisplayString(final InventoryItem item, final int qty, final boolean forTitle) {
final List<InventoryItem> items = new ArrayList<InventoryItem>();
items.add(item);
return getItemDisplayString(items, qty, forTitle);
}
public static String getItemDisplayString(final Iterable<? extends InventoryItem> items, final int qty, final boolean forTitle) {
//determine shared type among items
int itemCount = 0;
String sharedType = null;
boolean checkForSharedType = true;
for (final InventoryItem item : items) {
if (checkForSharedType) {
if (sharedType == null) {
sharedType = item.getItemType();
}
else if (!item.getItemType().equals(sharedType)) {
sharedType = null;
checkForSharedType = false;
}
}
itemCount++;
}
if (sharedType == null) {
sharedType = "Item"; //if no shared type, use generic "item"
}
//build display string based on shared type, item count, and quantity of each item
String result;
if (forTitle) { //convert to lowercase if not for title
result = sharedType;
if (itemCount != 1 || qty != 1) {
result += "s";
}
}
else {
result = sharedType.toLowerCase();
if (itemCount != 1) {
result = itemCount + " " + result + "s";
}
if (qty < 0) { //treat negative numbers as unknown quantity
result = "X copies of " + result;
}
else if (qty != 1) {
result = qty + " copies of " + result;
}
}
return result;
}
public static String buildDisplayList(final Iterable<Entry<InventoryItem, Integer>> items) {
final List<Entry<InventoryItem, Integer>> sorted = new ArrayList<Entry<InventoryItem, Integer>>();
for (final Entry<InventoryItem, Integer> itemEntry : items) {
sorted.add(itemEntry);
}
Collections.sort(sorted, new Comparator<Entry<InventoryItem, Integer>>() {
@Override
public int compare(final Entry<InventoryItem, Integer> x, final Entry<InventoryItem, Integer> y) {
return x.getKey().toString().compareTo(y.getKey().toString());
}
});
final StringBuilder builder = new StringBuilder();
for (final Entry<InventoryItem, Integer> itemEntry : sorted) {
builder.append("\n" + itemEntry.getValue() + " * " + itemEntry.getKey().toString());
}
return builder.toString();
}
private static final GroupDef[] CARD_GROUPBY_OPTIONS = { GroupDef.DEFAULT, GroupDef.CARD_TYPE, GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET, GroupDef.CARD_RARITY };
private static final GroupDef[] DECK_GROUPBY_OPTIONS = { GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET };
private static final ColumnDef[] CARD_PILEBY_OPTIONS = { ColumnDef.CMC, ColumnDef.COLOR, ColumnDef.NAME, ColumnDef.COST, ColumnDef.TYPE, ColumnDef.RARITY, ColumnDef.SET };
private static final ColumnDef[] DECK_PILEBY_OPTIONS = { ColumnDef.DECK_COLOR, ColumnDef.DECK_FOLDER, ColumnDef.NAME, ColumnDef.DECK_FORMAT, ColumnDef.DECK_EDITION };
public static void populateImageViewOptions(final IItemManager<?> itemManager, final IComboBox<Object> cbGroupByOptions, final IComboBox<Object> cbPileByOptions) {
final boolean isDeckManager = itemManager.getGenericType().equals(DeckProxy.class);
final GroupDef[] groupByOptions = isDeckManager ? DECK_GROUPBY_OPTIONS : CARD_GROUPBY_OPTIONS;
final ColumnDef[] pileByOptions = isDeckManager ? DECK_PILEBY_OPTIONS : CARD_PILEBY_OPTIONS;
cbGroupByOptions.addItem("(none)");
cbPileByOptions.addItem("(none)");
for (final GroupDef option : groupByOptions) {
cbGroupByOptions.addItem(option);
}
for (final ColumnDef option : pileByOptions) {
cbPileByOptions.addItem(option);
}
cbGroupByOptions.setSelectedIndex(0);
cbPileByOptions.setSelectedIndex(0);
}
}

View File

@@ -1,29 +1,29 @@
package forge.itemmanager;
import java.util.Iterator;
public class StringTokenizer implements Iterator<String> {
private String string;
private int index = 0;
public StringTokenizer(String string) {
this.string = string;
}
@Override
public boolean hasNext() {
return index < string.length();
}
@Override
public String next() {
return string.charAt(index++) + "";
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
}
package forge.itemmanager;
import java.util.Iterator;
public class StringTokenizer implements Iterator<String> {
private String string;
private int index = 0;
public StringTokenizer(String string) {
this.string = string;
}
@Override
public boolean hasNext() {
return index < string.length();
}
@Override
public String next() {
return string.charAt(index++) + "";
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
}

Some files were not shown because too many files have changed in this diff Show More