Deck builder now displays stats of the deck - shadow/FP card count and if the deck is valid for supported formats.

This commit is contained in:
marcins78@gmail.com
2011-09-18 18:25:19 +00:00
parent 4c53d38a54
commit 5d66af7e64
7 changed files with 129 additions and 33 deletions

View File

@@ -1,7 +1,7 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.Deck;
import com.gempukku.lotro.db.vo.Player;
import com.gempukku.lotro.logic.vo.LotroDeck;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -15,25 +15,25 @@ import java.util.concurrent.ConcurrentHashMap;
public class DeckDAO {
private DbAccess _dbAccess;
private Map<Integer, Map<String, Deck>> _decks = new ConcurrentHashMap<Integer, Map<String, Deck>>();
private Map<Integer, Map<String, LotroDeck>> _decks = new ConcurrentHashMap<Integer, Map<String, LotroDeck>>();
public DeckDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
public Deck getDeckForPlayer(Player player, String type) {
Map<String, Deck> playerDecks = _decks.get(player.getId());
public LotroDeck getDeckForPlayer(Player player, String type) {
Map<String, LotroDeck> playerDecks = _decks.get(player.getId());
if (playerDecks != null) {
Deck deck = playerDecks.get(type);
LotroDeck deck = playerDecks.get(type);
if (deck != null)
return deck;
}
Deck deck = getDeckFromDB(player.getId(), type);
LotroDeck deck = getDeckFromDB(player.getId(), type);
if (deck != null) {
Map<String, Deck> decksByType = _decks.get(player.getId());
Map<String, LotroDeck> decksByType = _decks.get(player.getId());
if (decksByType == null) {
decksByType = new ConcurrentHashMap<String, Deck>();
decksByType = new ConcurrentHashMap<String, LotroDeck>();
_decks.put(player.getId(), decksByType);
}
decksByType.put(type, deck);
@@ -42,22 +42,22 @@ public class DeckDAO {
return null;
}
public void setDeckForPlayer(Player player, String type, Deck deck) {
public void setDeckForPlayer(Player player, String type, LotroDeck deck) {
storeDeckToDB(player.getId(), type, deck);
Map<String, Deck> decksByType = _decks.get(player.getId());
Map<String, LotroDeck> decksByType = _decks.get(player.getId());
if (decksByType == null) {
decksByType = new ConcurrentHashMap<String, Deck>();
decksByType = new ConcurrentHashMap<String, LotroDeck>();
_decks.put(player.getId(), decksByType);
}
decksByType.put(type, deck);
}
private void storeDeckToDB(int playerId, String type, Deck deck) {
private void storeDeckToDB(int playerId, String type, LotroDeck deck) {
StringBuilder sb = new StringBuilder();
sb.append(deck.getRingBearer());
sb.append(",").append(deck.getRing());
appendList(sb, deck.getSites());
appendList(sb, deck.getDeck());
appendList(sb, deck.getAdventureCards());
String contents = sb.toString();
try {
@@ -73,7 +73,7 @@ public class DeckDAO {
sb.append("," + card);
}
private Deck getDeckFromDB(int playerId, String type) {
private LotroDeck getDeckFromDB(int playerId, String type) {
try {
String contents = getDeckContentsFromDB(playerId, type);
if (contents != null) {
@@ -86,9 +86,16 @@ public class DeckDAO {
}
}
private Deck buildDeckFromContents(String contents) {
private LotroDeck buildDeckFromContents(String contents) {
List<String> cardsList = Arrays.asList(contents.split(","));
return new Deck(cardsList.get(0), cardsList.get(1), cardsList.subList(2, 11), cardsList.subList(11, cardsList.size()));
LotroDeck deck = new LotroDeck();
deck.setRingBearer(cardsList.get(0));
deck.setRing(cardsList.get(1));
for (int i = 2; i < 11; i++)
deck.addSite(cardsList.get(i));
for (int i = 11; i < cardsList.size(); i++)
deck.addCard(cardsList.get(i));
return deck;
}
private void deleteDeckFromDB(int playerId, String type) throws SQLException {

View File

@@ -7,7 +7,6 @@ import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.db.DbAccess;
import com.gempukku.lotro.db.DeckDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.Deck;
import com.gempukku.lotro.db.vo.Player;
import com.gempukku.lotro.game.formats.LotroFormat;
import com.gempukku.lotro.logic.timing.GameResultListener;
@@ -124,7 +123,7 @@ public class LotroServer extends AbstractServer {
return gameId;
}
public Deck validateDeck(String contents) {
public LotroDeck validateDeck(String contents) {
List<String> cards = Arrays.asList(contents.split(","));
if (cards.size() < 11)
return null;
@@ -149,7 +148,14 @@ public class LotroServer extends AbstractServer {
for (String card : cards.subList(11, cards.size()))
_lotroCardBlueprintLibrary.getLotroCardBlueprint(card);
return new Deck(ringBearer, ring, cards.subList(2, 11), cards.subList(11, cards.size()));
LotroDeck deck = new LotroDeck();
deck.setRingBearer(cards.get(0));
deck.setRing(cards.get(1));
for (int i = 2; i < 11; i++)
deck.addSite(cards.get(i));
for (int i = 11; i < cards.size(); i++)
deck.addCard(cards.get(i));
return deck;
} catch (IllegalArgumentException exp) {
return null;
}
@@ -157,7 +163,7 @@ public class LotroServer extends AbstractServer {
public LotroDeck getParticipantDeck(String participantId) {
Player player = _playerDao.getPlayer(participantId);
Deck deck = _deckDao.getDeckForPlayer(player, "default");
LotroDeck deck = _deckDao.getDeckForPlayer(player, "default");
if (deck == null)
return null;
@@ -166,7 +172,7 @@ public class LotroServer extends AbstractServer {
lotroDeck.setRingBearer(deck.getRingBearer());
for (String site : deck.getSites())
lotroDeck.addSite(site);
for (String card : deck.getDeck())
for (String card : deck.getAdventureCards())
lotroDeck.addCard(card);
return lotroDeck;

View File

@@ -42,8 +42,8 @@ public class HallServer extends AbstractServer {
return _awaitingTables.size() + _runningTables.size();
}
public Set<String> getSupportedFormats() {
return new TreeSet<String>(_supportedFormats.keySet());
public Map<String, LotroFormat> getSupportedFormats() {
return new TreeMap<String, LotroFormat>(_supportedFormats);
}
/**

View File

@@ -3,15 +3,17 @@ package com.gempukku.lotro.server;
import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.common.Side;
import com.gempukku.lotro.db.DeckDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.Deck;
import com.gempukku.lotro.db.vo.Player;
import com.gempukku.lotro.game.*;
import com.gempukku.lotro.game.formats.LotroFormat;
import com.gempukku.lotro.hall.HallException;
import com.gempukku.lotro.hall.HallInfoVisitor;
import com.gempukku.lotro.hall.HallServer;
import com.gempukku.lotro.logic.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.vo.LotroDeck;
import com.sun.jersey.spi.resource.Singleton;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
@@ -204,7 +206,7 @@ public class ServerResource {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Deck deck = deckDao.getDeckForPlayer(player, deckType);
LotroDeck deck = deckDao.getDeckForPlayer(player, deckType);
if (deck == null) {
Document doc = documentBuilder.newDocument();
Element deckElem = doc.createElement("deck");
@@ -229,7 +231,7 @@ public class ServerResource {
site.setAttribute("blueprintId", s);
deckElem.appendChild(site);
}
for (String s : deck.getDeck()) {
for (String s : deck.getAdventureCards()) {
Element card = doc.createElement("card");
card.setAttribute("blueprintId", s);
deckElem.appendChild(card);
@@ -256,7 +258,7 @@ public class ServerResource {
if (player == null)
sendError(Response.Status.UNAUTHORIZED);
Deck deck = _lotroServer.validateDeck(contents);
LotroDeck deck = _lotroServer.validateDeck(contents);
if (deck == null)
sendError(Response.Status.BAD_REQUEST);
@@ -272,6 +274,48 @@ public class ServerResource {
return doc;
}
@Path("/deck")
@POST
@Produces("text/html")
public String getDeckStats(
@FormParam("participantId") String participantId,
@FormParam("deckContents") String contents,
@Context HttpServletRequest request) {
if (!_test)
participantId = getLoggedUser(request);
LotroDeck deck = _lotroServer.validateDeck(contents);
if (deck == null)
sendError(Response.Status.BAD_REQUEST);
int fpCount = 0;
int shadowCount = 0;
LotroCardBlueprintLibrary library = _lotroServer.getLotroCardBlueprintLibrary();
for (String card : deck.getAdventureCards()) {
Side side = library.getLotroCardBlueprint(card).getSide();
if (side == Side.SHADOW)
shadowCount++;
else if (side == Side.FREE_PEOPLE)
fpCount++;
}
StringBuilder sb = new StringBuilder();
sb.append("<b>Free People</b>: " + fpCount + ", <b>Shadow</b>: " + shadowCount + "<br/>");
for (Map.Entry<String, LotroFormat> supportedFormats : _hallServer.getSupportedFormats().entrySet()) {
String formatName = supportedFormats.getKey();
LotroFormat format = supportedFormats.getValue();
try {
format.validateDeck(deck);
sb.append("<b>" + formatName + "</b>: <font color='green'>valid</font> ");
} catch (DeckInvalidException exp) {
sb.append("<b>" + formatName + "</b>: <font color='red'>" + exp.getMessage() + "</font> ");
}
}
return sb.toString();
}
@Path("/collection/{collectionType}")
@GET
@Produces(MediaType.APPLICATION_XML)
@@ -392,7 +436,7 @@ public class ServerResource {
Element hall = doc.createElement("hall");
_hallServer.processTables(participantId, new SerializeHallInfoVisitor(doc, hall));
for (String format : _hallServer.getSupportedFormats()) {
for (String format : _hallServer.getSupportedFormats().keySet()) {
Element formatElem = doc.createElement("format");
formatElem.appendChild(doc.createTextNode(format));
hall.appendChild(formatElem);

View File

@@ -28,6 +28,10 @@
width: 350px;
}
#deckStats {
color: #ffffff;
}
</style>
<link rel="stylesheet" type="text/css" href="css/dark-hive/jquery-ui-1.8.16.custom.css">
<link rel="stylesheet" type="text/css" href="js/jquery/styles/jquery.spinnercontrol.css">

View File

@@ -95,6 +95,19 @@ var GempLotrCommunication = Class.extend({
dataType: "xml"
});
},
getDeckStats: function(contents, callback) {
$.ajax({
type: "POST",
url: this.url + "/deck",
cache: false,
data: {
participantId: getUrlParam("participantId"),
deckContents: contents},
success: callback,
error: this.failure,
dataType: "html"
});
},
startChat: function(room, callback) {
$.ajax({
type: "GET",

View File

@@ -176,6 +176,7 @@ var GempLotrDeckBuildingUI = Class.extend({
this.bottomBarDiv = $("<div></div>");
this.bottomBarDiv.append("<button id='saveDeck' style='float: right;'>Save deck</button>");
this.bottomBarDiv.append("<div id='deckStats'></div>")
this.deckDiv.append(this.bottomBarDiv);
$("#saveDeck").button().click(
function() {
@@ -197,8 +198,10 @@ var GempLotrDeckBuildingUI = Class.extend({
that.displayCardInfo(selectedCardElem.data("card"));
} else if (selectedCardElem.hasClass("cardInCollection")) {
that.selectionFunc(selectedCardElem.data("card").blueprintId);
that.updateDeckStats();
} else if (selectedCardElem.hasClass("cardInDeck")) {
that.removeCardFromDeck(selectedCardElem);
that.updateDeckStats();
}
return false;
}
@@ -242,7 +245,7 @@ var GempLotrDeckBuildingUI = Class.extend({
this.infoDialog.dialog("open");
},
saveDeck: function() {
getDeckContents: function() {
var ringBearer = $(".card", this.ringBearerDiv);
var ring = $(".card", this.ringDiv);
var site1 = $(".card", this.siteDivs[0]);
@@ -257,7 +260,7 @@ var GempLotrDeckBuildingUI = Class.extend({
if (ringBearer.length == 0 || ring.length == 0 || site1.length == 0 || site2.length == 0 || site3.length == 0 || site4.length == 0
|| site5.length == 0 || site6.length == 0 || site7.length == 0 || site8.length == 0 || site9.length == 0) {
alert("To save a deck, it must have at least a Ring-Bearer, Ring and all 9 sites set");
return null;
} else {
var cards = new Array();
cards.push(ringBearer.data("card").blueprintId);
@@ -277,10 +280,18 @@ var GempLotrDeckBuildingUI = Class.extend({
cards.push($(this).data("card").blueprintId);
});
this.comm.saveDeck("default", "" + cards, function(xml) {
return "" + cards;
}
},
saveDeck: function() {
var deckContents = this.getDeckContents();
if (deckContents == null)
alert("Deck must contain at least Ring-bearer, The One Ring and 9 sites");
else
this.comm.saveDeck("default", deckContents, function(xml) {
alert("Deck was saved");
});
}
},
addCardToContainer: function(blueprintId, zone, container) {
@@ -350,6 +361,15 @@ var GempLotrDeckBuildingUI = Class.extend({
}
},
updateDeckStats: function() {
var deckContents = this.getDeckContents();
if (deckContents != null)
this.comm.getDeckStats(deckContents,
function(html) {
$("#deckStats").html(html);
});
},
removeCardFromDeck: function(cardDiv) {
var cardData = cardDiv.data("card");
if (cardData.attachedCards.length > 0) {
@@ -386,6 +406,8 @@ var GempLotrDeckBuildingUI = Class.extend({
this.layoutUI();
}
this.updateDeckStats();
this.getCollection();
}
},
@@ -452,7 +474,7 @@ var GempLotrDeckBuildingUI = Class.extend({
this.drawDeckDiv.css({ position: "absolute", left: padding * 3 + sitesWidth * 2, top: padding, width: deckWidth - (sitesWidth + padding) * 2 - padding, height: deckHeight - 2 * padding - 50 });
this.drawDeckGroup.setBounds(0, 0, deckWidth - (sitesWidth + padding) * 2 - padding, deckHeight - 2 * padding - 50);
this.bottomBarDiv.css({ position: "absolute", left: sitesWidth * 2, top: deckHeight - 50, width: deckWidth - sitesWidth * 2, height: 50 });
this.bottomBarDiv.css({ position: "absolute", left: padding * 3 + sitesWidth * 2, top: deckHeight - 50, width: deckWidth - (sitesWidth + padding) * 2 - padding, height: 50 });
this.filterDiv.css({ position: "absolute", left: padding, top: 50, width: collectionWidth - padding, height: 50 });
this.normalCollectionDiv.css({ position: "absolute", left: padding, top: 100, width: collectionWidth - padding * 2, height: collectionHeight - 100 });