Various changes relating to the collection rework; not yet done or working

This commit is contained in:
Christian 'ketura' McCarty
2022-10-25 02:14:18 -05:00
parent a9b8488b75
commit 03751d6b9d
17 changed files with 393 additions and 162 deletions

View File

@@ -0,0 +1,18 @@
ALTER TABLE collection ADD CONSTRAINT fk_collection_player_id FOREIGN KEY (player_id) REFERENCES player(id);
CREATE TABLE `collection_entries` (
`collection_id` int(11) NOT NULL,
`quantity` int(2) DEFAULT 0,
`product_type` varchar(50) NOT NULL,
`product_variant` varchar(50) DEFAULT NULL,
`product` varchar(50) NOT NULL,
`source` varchar(50) NOT NULL,
`created_date` datetime DEFAULT current_timestamp(),
`modified_date` datetime DEFAULT NULL ON UPDATE current_timestamp(),
`notes` varchar(100) DEFAULT NULL,
PRIMARY KEY (`collection_id`, `product`),
CONSTRAINT `collection_entries_ibfk_1` FOREIGN KEY (`collection_id`) REFERENCES `collection` (`id`)
) ;

View File

@@ -2,7 +2,7 @@ package com.gempukku.lotro.async.handler;
import com.gempukku.lotro.async.HttpProcessingException;
import com.gempukku.lotro.async.ResponseWriter;
import com.gempukku.lotro.db.vo.GameHistoryEntry;
import com.gempukku.lotro.common.DBDefs;
import com.gempukku.lotro.game.GameHistoryService;
import com.gempukku.lotro.game.Player;
import io.netty.handler.codec.http.HttpMethod;
@@ -42,7 +42,7 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
Player resourceOwner = getResourceOwnerSafely(request, participantId);
final List<GameHistoryEntry> playerGameHistory = _gameHistoryService.getGameHistoryForPlayer(resourceOwner, start, count);
final List<DBDefs.GameHistory> playerGameHistory = _gameHistoryService.getGameHistoryForPlayer(resourceOwner, start, count);
int recordCount = _gameHistoryService.getGameHistoryForPlayerCount(resourceOwner);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
@@ -52,29 +52,29 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
gameHistory.setAttribute("count", String.valueOf(recordCount));
gameHistory.setAttribute("playerId", resourceOwner.getName());
for (GameHistoryEntry gameHistoryEntry : playerGameHistory) {
for (DBDefs.GameHistory game : playerGameHistory) {
Element historyEntry = doc.createElement("historyEntry");
historyEntry.setAttribute("winner", gameHistoryEntry.winner);
historyEntry.setAttribute("loser", gameHistoryEntry.loser);
historyEntry.setAttribute("winner", game.winner);
historyEntry.setAttribute("loser", game.loser);
historyEntry.setAttribute("winReason", gameHistoryEntry.win_reason);
historyEntry.setAttribute("loseReason", gameHistoryEntry.lose_reason);
historyEntry.setAttribute("winReason", game.win_reason);
historyEntry.setAttribute("loseReason", game.lose_reason);
historyEntry.setAttribute("formatName", gameHistoryEntry.format_name);
String tournament = gameHistoryEntry.tournament;
historyEntry.setAttribute("formatName", game.format_name);
String tournament = game.tournament;
if (tournament != null)
historyEntry.setAttribute("tournament", tournament);
if (gameHistoryEntry.winner.equals(resourceOwner.getName()) && gameHistoryEntry.win_recording_id != null) {
historyEntry.setAttribute("gameRecordingId", gameHistoryEntry.win_recording_id);
historyEntry.setAttribute("deckName", gameHistoryEntry.winner_deck_name);
} else if (gameHistoryEntry.loser.equals(resourceOwner.getName()) && gameHistoryEntry.lose_recording_id != null) {
historyEntry.setAttribute("gameRecordingId", gameHistoryEntry.lose_recording_id);
historyEntry.setAttribute("deckName", gameHistoryEntry.loser_deck_name);
if (game.winner.equals(resourceOwner.getName()) && game.win_recording_id != null) {
historyEntry.setAttribute("gameRecordingId", game.win_recording_id);
historyEntry.setAttribute("deckName", game.winner_deck_name);
} else if (game.loser.equals(resourceOwner.getName()) && game.lose_recording_id != null) {
historyEntry.setAttribute("gameRecordingId", game.lose_recording_id);
historyEntry.setAttribute("deckName", game.loser_deck_name);
}
historyEntry.setAttribute("startTime", String.valueOf(gameHistoryEntry.GetStartDate().getTime()));
historyEntry.setAttribute("endTime", String.valueOf(gameHistoryEntry.GetEndDate().getTime()));
historyEntry.setAttribute("startTime", String.valueOf(game.GetStartDate().getTime()));
historyEntry.setAttribute("endTime", String.valueOf(game.GetEndDate().getTime()));
gameHistory.appendChild(historyEntry);
}
@@ -83,7 +83,7 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
responseWriter.writeXmlResponse(doc);
} else if (uri.equals("/list") && request.method() == HttpMethod.GET) {
final List<GameHistoryEntry> playerGameHistory = _gameHistoryService.getTrackableGames(100);
final List<DBDefs.GameHistory> playerGameHistory = _gameHistoryService.getTrackableGames(100);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
@@ -92,24 +92,24 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (GameHistoryEntry gameHistoryEntry : playerGameHistory) {
for (DBDefs.GameHistory game : playerGameHistory) {
Element historyEntry = doc.createElement("historyEntry");
historyEntry.setAttribute("winner", gameHistoryEntry.winner);
historyEntry.setAttribute("loser", gameHistoryEntry.loser);
historyEntry.setAttribute("winner", game.winner);
historyEntry.setAttribute("loser", game.loser);
historyEntry.setAttribute("winReason", gameHistoryEntry.win_reason);
historyEntry.setAttribute("loseReason", gameHistoryEntry.lose_reason);
historyEntry.setAttribute("winReason", game.win_reason);
historyEntry.setAttribute("loseReason", game.lose_reason);
historyEntry.setAttribute("formatName", gameHistoryEntry.format_name);
historyEntry.setAttribute("formatName", game.format_name);
historyEntry.setAttribute("winnerRecordingLink", "http://www.gempukku.com/gemp-lotr/game.html?replayId="+gameHistoryEntry.winner+"$"+gameHistoryEntry.win_recording_id);
historyEntry.setAttribute("winnerDeckName", gameHistoryEntry.winner_deck_name);
historyEntry.setAttribute("winnerRecordingLink", "http://www.gempukku.com/gemp-lotr/game.html?replayId="+game.winner+"$"+game.win_recording_id);
historyEntry.setAttribute("winnerDeckName", game.winner_deck_name);
historyEntry.setAttribute("loserRecordingLink", "http://www.gempukku.com/gemp-lotr/game.html?replayId="+gameHistoryEntry.loser+"$"+gameHistoryEntry.lose_recording_id);
historyEntry.setAttribute("loserDeckName", gameHistoryEntry.loser_deck_name);
historyEntry.setAttribute("loserRecordingLink", "http://www.gempukku.com/gemp-lotr/game.html?replayId="+game.loser+"$"+game.lose_recording_id);
historyEntry.setAttribute("loserDeckName", game.loser_deck_name);
historyEntry.setAttribute("startTime", dateFormat.format(new Date(gameHistoryEntry.GetStartDate().getTime())));
historyEntry.setAttribute("endTime", dateFormat.format(new Date(gameHistoryEntry.GetEndDate().getTime())));
historyEntry.setAttribute("startTime", dateFormat.format(new Date(game.GetStartDate().getTime())));
historyEntry.setAttribute("endTime", dateFormat.format(new Date(game.GetEndDate().getTime())));
gameHistory.appendChild(historyEntry);
}
@@ -118,7 +118,7 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
responseWriter.writeXmlResponse(doc);
} else if (uri.equals("/list/html") && request.method() == HttpMethod.GET) {
final List<GameHistoryEntry> playerGameHistory = _gameHistoryService.getTrackableGames(100);
final List<DBDefs.GameHistory> playerGameHistory = _gameHistoryService.getTrackableGames(100);
StringBuilder sb = new StringBuilder();
sb.append("<html><body><table>");
@@ -133,16 +133,16 @@ public class GameHistoryRequestHandler extends LotroServerRequestHandler impleme
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (GameHistoryEntry gameHistoryEntry : playerGameHistory) {
String winnerLink = "http://www.gempukku.com/gemp-lotr/game.html?replayId=" + gameHistoryEntry.winner + "$" + gameHistoryEntry.win_recording_id;
String loserLink = "http://www.gempukku.com/gemp-lotr/game.html?replayId=" + gameHistoryEntry.loser + "$" + gameHistoryEntry.lose_recording_id;
for (DBDefs.GameHistory game : playerGameHistory) {
String winnerLink = "http://www.gempukku.com/gemp-lotr/game.html?replayId=" + game.winner + "$" + game.win_recording_id;
String loserLink = "http://www.gempukku.com/gemp-lotr/game.html?replayId=" + game.loser + "$" + game.lose_recording_id;
sb.append("<tr>");
sb.append("<td rowspan='2'>" + dateFormat.format(new Date(gameHistoryEntry.GetStartDate().getTime())) + "</td><td rowspan='2'>" + dateFormat.format(new Date(gameHistoryEntry.GetEndDate().getTime())) + "</td>");
sb.append("<td>" + gameHistoryEntry.winner + "</td><td>" + gameHistoryEntry.win_reason + "</td><td>" + gameHistoryEntry.winner_deck_name + "</td><td><a target='_blank' href='" + winnerLink + "'>Replay</a></td>");
sb.append("<td rowspan='2'>" + dateFormat.format(new Date(game.GetStartDate().getTime())) + "</td><td rowspan='2'>" + dateFormat.format(new Date(game.GetEndDate().getTime())) + "</td>");
sb.append("<td>" + game.winner + "</td><td>" + game.win_reason + "</td><td>" + game.winner_deck_name + "</td><td><a target='_blank' href='" + winnerLink + "'>Replay</a></td>");
sb.append("</tr>");
sb.append("<tr>");
sb.append("<td>" + gameHistoryEntry.loser + "</td><td>" + gameHistoryEntry.lose_reason + "</td><td>" + gameHistoryEntry.lose_reason + "</td><td><a target='_blank' href='" + loserLink + "'>Replay</a></td>");
sb.append("<td>" + game.loser + "</td><td>" + game.lose_reason + "</td><td>" + game.lose_reason + "</td><td><a target='_blank' href='" + loserLink + "'>Replay</a></td>");
sb.append("</tr>");
}

View File

@@ -2,20 +2,22 @@ package com.gempukku.lotro.async.handler;
import com.gempukku.lotro.async.HttpProcessingException;
import com.gempukku.lotro.async.ResponseWriter;
import com.gempukku.lotro.common.DBDefs;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.GameHistoryEntry;
import com.gempukku.lotro.game.*;
import com.gempukku.lotro.game.GameHistoryService;
import com.gempukku.lotro.game.Player;
import com.google.gson.Gson;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.google.gson.Gson;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.lang.reflect.Type;
import java.util.*;
import java.util.List;
import java.util.Map;
public class PlaytestRequestHandler extends LotroServerRequestHandler implements UriRequestHandler {
@@ -98,7 +100,7 @@ public class PlaytestRequestHandler extends LotroServerRequestHandler implements
String format = getFormParameterSafely(postDecoder, "format");
int count = Integer.parseInt(getFormParameterSafely(postDecoder, "count"));
final List<GameHistoryEntry> gameHistory = _gameHistoryService.getGameHistoryForFormat(format, count);
final List<DBDefs.GameHistory> gameHistory = _gameHistoryService.getGameHistoryForFormat(format, count);
responseWriter.writeJsonResponse(JsonConvert.toJson(gameHistory));

View File

@@ -1512,7 +1512,7 @@
12xRoS - Booster
12xTaD - Booster
#Frodo, Weary From the Journey
1x11_144
1x15_144
#The One Ring, The Ruling Ring
1x15_2
#Anduin River
@@ -1563,7 +1563,7 @@
format: limited_multipath
seriesProduct: [
[
1x(S)Movie Special Choice - Starter
1x(S)Movie Choice - Starter
1xFotR - Booster
1xMoM - Booster
1xRotEL - Booster

View File

@@ -0,0 +1,56 @@
package com.gempukku.lotro.common;
import java.time.LocalDateTime;
import java.util.Date;
public class DBDefs {
public static class GameHistory {
public int id;
public String winner;
public String loser;
public String win_reason;
public String lose_reason;
public String win_recording_id;
public String lose_recording_id;
public long start_date;
public long end_date;
public String format_name;
public String winner_deck_name;
public String loser_deck_name;
public String tournament;
public Date GetStartDate()
{
return new Date(start_date);
}
public Date GetEndDate()
{
return new Date(end_date);
}
}
public static class CollectionEntry {
public int collection_id;
public int quantity;
public String product_type;
public String product_variant;
public String product;
public String source;
public LocalDateTime created_date;
public LocalDateTime modified_date;
public String notes;
}
}

View File

@@ -53,4 +53,27 @@ public class CachedCollectionDAO implements CollectionDAO, Cached {
_delegate.setPlayerCollection(playerId, type, collection);
_playerCollections.put(constructCacheKey(playerId, type), collection);
}
@Override
public void convertCollection(int playerId, String type) throws SQLException, IOException {
_delegate.convertCollection(playerId, type);
}
@Override
public void addToCollection(int playerId, String type, CardCollection collection, String source) {
_delegate.addToCollection(playerId, type, collection, source);
String id = constructCacheKey(playerId, type);
if(!_playerCollections.containsKey(id)) {
_playerCollections.put(id, collection);
}
else {
var oldCollection = _playerCollections.get(id);
//oldCollection.
}
}
@Override
public void removeFromCollection(int playerId, String type, CardCollection collection, String source) {
_delegate.removeFromCollection(playerId, type, collection, source);
}
}

View File

@@ -1,19 +1,18 @@
package com.gempukku.lotro.collection;
import com.gempukku.lotro.common.CardType;
import com.gempukku.lotro.db.CollectionDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.game.*;
import com.gempukku.lotro.packs.PacksStorage;
import com.gempukku.lotro.packs.ProductLibrary;
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
public class CollectionsManager {
private final ReentrantReadWriteLock _readWriteLock = new ReentrantReadWriteLock();
@@ -31,46 +30,7 @@ public class CollectionsManager {
}
public CardCollection getDefaultCollection() {
return new CardCollection() {
@Override
public int getCurrency() {
return 0;
}
@Override
public Iterable<Item> getAll() {
return lotroCardBlueprintLibrary.getBaseCards().entrySet().stream().map(cardBlueprintEntry -> {
String blueprintId = cardBlueprintEntry.getKey();
int count = getCount(cardBlueprintEntry.getValue());
return Item.createItem(blueprintId, count);
}).collect(Collectors.toList());
}
@Override
public int getItemCount(String blueprintId) {
final String baseBlueprintId = lotroCardBlueprintLibrary.getBaseBlueprintId(blueprintId);
if (baseBlueprintId.equals(blueprintId)) {
try {
return getCount(lotroCardBlueprintLibrary.getLotroCardBlueprint(blueprintId));
} catch (CardNotFoundException exp) {
return 0;
}
}
return 0;
}
private int getCount(LotroCardBlueprint blueprint) {
final CardType cardType = blueprint.getCardType();
if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING)
return 1;
return 4;
}
@Override
public Map<String, Object> getExtraInformation() {
return Collections.emptyMap();
}
};
return new CompleteCardCollection(lotroCardBlueprintLibrary);
}
public CardCollection getPlayerCollection(String playerName, String collectionType) {
@@ -134,6 +94,16 @@ public class CollectionsManager {
}
}
public void upgradePlayerCollection(Player player, CollectionType colltype) throws SQLException, IOException {
_readWriteLock.writeLock().lock();
try {
//var collection = _collectionDAO.getPlayerCollection(player.getId(), colltype.getCode());
_collectionDAO.convertCollection(player.getId(), colltype.getCode());
} finally {
_readWriteLock.writeLock().unlock();
}
}
public Map<Player, CardCollection> getPlayersCollection(String collectionType) {
if (collectionType.contains("+"))
throw new IllegalArgumentException("Invalid collection type: " + collectionType);

View File

@@ -12,4 +12,10 @@ public interface CollectionDAO {
public CardCollection getPlayerCollection(int playerId, String type) throws SQLException, IOException;
public void setPlayerCollection(int playerId, String type, CardCollection collection) throws SQLException, IOException;
void convertCollection(int playerId, String type) throws SQLException, IOException;
void addToCollection(int playerId, String type, CardCollection collection, String source);
void removeFromCollection(int playerId, String type, CardCollection collection, String source);
}

View File

@@ -8,25 +8,30 @@ import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import javax.sql.DataSource;
import java.util.Properties;
public class DbAccess {
private final DataSource _dataSource;
public DbAccess() {
this(AppConfig.getProperty("db.connection.url"), AppConfig.getProperty("db.connection.username"), AppConfig.getProperty("db.connection.password"), false);
}
public DbAccess(String url, String user, String pass, boolean batch) {
try {
Class.forName(AppConfig.getProperty("db.connection.class"));
} catch (ClassNotFoundException e) {
throw new RuntimeException("Couldn't find the DB driver", e);
}
_dataSource = setupDataSource(AppConfig.getProperty("db.connection.url"));
_dataSource = setupDataSource(url, user, pass, batch);
}
public DataSource getDataSource() {
return _dataSource;
}
private DataSource setupDataSource(String connectURI) {
private DataSource setupDataSource(String connectURI, String user, String pass, Boolean batch) {
//
// First, we'll create a ConnectionFactory that the
// pool will use to create Connections.
@@ -34,9 +39,14 @@ public class DbAccess {
// using the connect string passed in the command line
// arguments.
//
Properties props = new Properties() {{
setProperty("user", user);
setProperty("password", pass);
setProperty("rewriteBatchedStatements", batch.toString().toLowerCase());
setProperty("innodb_autoinc_lock_mode", "2");
}};
ConnectionFactory connectionFactory =
new DriverManagerConnectionFactory(connectURI, AppConfig.getProperty("db.connection.username"),
AppConfig.getProperty("db.connection.password"));
new DriverManagerConnectionFactory(connectURI, props);
//
// Now we'll need a ObjectPool that serves as the

View File

@@ -2,6 +2,8 @@ package com.gempukku.lotro.db;
import com.gempukku.lotro.collection.CollectionSerializer;
import com.gempukku.lotro.game.CardCollection;
import org.sql2o.Query;
import org.sql2o.Sql2o;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -85,4 +87,109 @@ public class DbCollectionDAO implements CollectionDAO {
}
}
}
private class intContainer {
public int ID;
}
public int getCollectionID(int playerId, String type) {
try {
Sql2o db = new Sql2o(_dbAccess.getDataSource());
try (org.sql2o.Connection conn = db.open()) {
String sql = """
SELECT
ID
FROM collection
WHERE type = :type
AND player_id = :playerID
LIMIT 1
""";
intContainer result = conn.createQuery(sql)
.addParameter("type", type)
.addParameter("playerID", playerId)
.executeAndFetch(intContainer.class)
.stream().findFirst().orElse(null);
return result.ID;
}
} catch (Exception ex) {
throw new RuntimeException("Unable to retrieve collection ID", ex);
}
}
public void updateCollection(int playerId, String type, CardCollection collection, String source) {
String sql = """
INSERT INTO collection_entries(collection_id, quantity, product_type, product, source)
VALUES (:collid, :quantity, :type, :product, :source)
ON DUPLICATE KEY UPDATE quantity = :quantity, source = :source;
""";
String error = "Unable to update product via upsert into collection_entries.";
updateCollection(playerId, type, collection, source, sql, error);
}
public void addToCollection(int playerId, String type, CardCollection collection, String source) {
String sql = """
INSERT INTO collection_entries(collection_id, quantity, product_type, product, source)
VALUES (:collid, :quantity, :type, :product, :source)
ON DUPLICATE KEY UPDATE quantity = quantity + :quantity, source = :source;
""";
String error = "Unable to add product via upsert into collection_entries.";
updateCollection(playerId, type, collection, source, sql, error);
}
public void removeFromCollection(int playerId, String type, CardCollection collection, String source) {
String sql = """
INSERT INTO collection_entries(collection_id, quantity, product_type, product, source)
VALUES (:collid, :quantity, :type, :product, :source)
ON DUPLICATE KEY UPDATE quantity = GREATEST(quantity - :quantity, 0), source = :source;
""";
String error = "Unable to remove product via upsert into collection_entries.";
updateCollection(playerId, type, collection, source, sql, error);
}
public void convertCollection(int playerId, String type) throws SQLException, IOException {
CardCollection oldCollection = getPlayerCollection(playerId, type);
updateCollection(playerId, type, oldCollection, "Initial Convert");
}
//TODO:
// - Convert currency to an extra info entry
// - add data field to the original collection table to hold the extra info as json
// - create player-looping function to convert all collections and see if it blows up via test
// - add CollectionsManager mirror functions to read/writing into the new table
// - write unit tests to convert and compare a bajillion collections
// - sunset the old collection handling functions
// - test a: draft, new art card reward, my cards reward, pack openings
// - write script to back up db and delete the old binary blob column
// - write script to convert all leagues to use IDs instead of names
private void updateCollection(int playerId, String type, CardCollection collection, String source, String sql, String error) {
int collID = getCollectionID(playerId, type);
try {
Sql2o db = new Sql2o(_dbAccess.getDataSource());
try (org.sql2o.Connection conn = db.beginTransaction()) {
Query query = conn.createQuery(sql, true);
int i = 0;
//TODO: maybe detect when the batch is 1000 entries long and execute then to prevent errors
for(var card : collection.getAll()) {
query.addParameter("collid", collID)
.addParameter("quantity", card.getCount())
.addParameter("type", card.getType())
.addParameter("product", card.getBlueprintId())
.addParameter("source", source)
.addToBatch();
}
query.executeBatch();
conn.commit();
}
} catch (Exception ex) {
throw new RuntimeException(error, ex);
}
}
}

View File

@@ -1,6 +1,6 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.GameHistoryEntry;
import com.gempukku.lotro.common.DBDefs;
import com.gempukku.lotro.game.Player;
import org.sql2o.Sql2o;
@@ -42,7 +42,7 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
}
}
public List<GameHistoryEntry> getGameHistoryForPlayer(Player player, int start, int count) {
public List<DBDefs.GameHistory> getGameHistoryForPlayer(Player player, int start, int count) {
try {
@@ -50,11 +50,11 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
try (org.sql2o.Connection conn = db.open()) {
String sql = "select winner, loser, win_reason, lose_reason, win_recording_id, lose_recording_id, format_name, tournament, winner_deck_name, loser_deck_name, start_date, end_date from game_history where winner=:playerName or loser=:playerName order by end_date desc limit :start, :count";
List<GameHistoryEntry> result = conn.createQuery(sql)
List<DBDefs.GameHistory> result = conn.createQuery(sql)
.addParameter("playerName", player.getName())
.addParameter("start", start)
.addParameter("count", count)
.executeAndFetch(GameHistoryEntry.class);
.executeAndFetch(DBDefs.GameHistory.class);
return result;
}
@@ -65,20 +65,27 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
}
@Override
public List<GameHistoryEntry> getGameHistoryForFormat(String format, int count) {
public List<DBDefs.GameHistory> getGameHistoryForFormat(String format, int count) {
try {
Sql2o db = new Sql2o(_dbAccess.getDataSource());
try (org.sql2o.Connection conn = db.open()) {
String sql = "SELECT winner, loser, win_reason, lose_reason, win_recording_id, lose_recording_id, format_name, tournament, winner_deck_name, loser_deck_name, start_date, end_date " +
" FROM game_history " +
" WHERE format_name LIKE :format" +
" ORDER BY end_date DESC LIMIT :count";
List<GameHistoryEntry> result = conn.createQuery(sql)
String sql = """
SELECT
winner, loser, win_reason, lose_reason,
win_recording_id, lose_recording_id, format_name,
tournament, winner_deck_name, loser_deck_name,
start_date, end_date
FROM game_history
WHERE format_name LIKE :format
ORDER BY end_date DESC
LIMIT :count
""";
List<DBDefs.GameHistory> result = conn.createQuery(sql)
.addParameter("format", "%" + format + "%")
.addParameter("count", count)
.executeAndFetch(GameHistoryEntry.class);
.executeAndFetch(DBDefs.GameHistory.class);
return result;
}
@@ -191,7 +198,7 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
}
@Override
public List<GameHistoryEntry> getLastGames(String requestedFormatName, int count) {
public List<DBDefs.GameHistory> getLastGames(String requestedFormatName, int count) {
try {
@@ -201,10 +208,10 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
String sql = "select winner, loser, win_reason, lose_reason, win_recording_id, lose_recording_id, format_name, " +
"tournament, winner_deck_name, loser_deck_name, start_date, end_date from game_history " +
"where format_name=:formatName order by end_date desc limit :count";
List<GameHistoryEntry> result = conn.createQuery(sql)
List<DBDefs.GameHistory> result = conn.createQuery(sql)
.addParameter("formatName", requestedFormatName)
.addParameter("count", count)
.executeAndFetch(GameHistoryEntry.class);
.executeAndFetch(DBDefs.GameHistory.class);
return result;
}

View File

@@ -1,6 +1,6 @@
package com.gempukku.lotro.db;
import com.gempukku.lotro.db.vo.GameHistoryEntry;
import com.gempukku.lotro.common.DBDefs;
import com.gempukku.lotro.game.Player;
import java.util.Date;
@@ -10,11 +10,11 @@ import java.util.Map;
public interface GameHistoryDAO {
public void addGameHistory(String winner, String loser, String winReason, String loseReason, String winRecordingId, String loseRecordingId, String formatName, String tournament, String winnerDeckName, String loserDeckName, Date startDate, Date endDate);
public List<GameHistoryEntry> getGameHistoryForPlayer(Player player, int start, int count);
public List<DBDefs.GameHistory> getGameHistoryForPlayer(Player player, int start, int count);
public int getGameHistoryForPlayerCount(Player player);
public List<GameHistoryEntry> getGameHistoryForFormat(String format, int count);
public List<DBDefs.GameHistory> getGameHistoryForFormat(String format, int count);
public int getActivePlayersCount(long from, long duration);
@@ -26,5 +26,5 @@ public interface GameHistoryDAO {
public List<PlayerStatistic> getCompetitivePlayerStatistics(Player player);
List<GameHistoryEntry> getLastGames(String formatName, int count);
List<DBDefs.GameHistory> getLastGames(String formatName, int count);
}

View File

@@ -2,39 +2,4 @@ package com.gempukku.lotro.db.vo;
import java.util.Date;
public class GameHistoryEntry {
public int id;
public String winner;
public String loser;
public String win_reason;
public String lose_reason;
public String win_recording_id;
public String lose_recording_id;
public long start_date;
public long end_date;
public String format_name;
public String winner_deck_name;
public String loser_deck_name;
public String tournament;
public Date GetStartDate()
{
return new Date(start_date);
}
public Date GetEndDate()
{
return new Date(end_date);
}
}

View File

@@ -0,0 +1,54 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.common.CardType;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
public class CompleteCardCollection implements CardCollection {
private final LotroCardBlueprintLibrary _library;
public CompleteCardCollection(LotroCardBlueprintLibrary library) {
_library = library;
}
@Override
public int getCurrency() {
return 0;
}
@Override
public Iterable<Item> getAll() {
return _library.getBaseCards().entrySet().stream().map(cardBlueprintEntry -> {
String blueprintId = cardBlueprintEntry.getKey();
int count = getCount(cardBlueprintEntry.getValue());
return Item.createItem(blueprintId, count);
}).collect(Collectors.toList());
}
@Override
public int getItemCount(String blueprintId) {
final String baseBlueprintId = _library.getBaseBlueprintId(blueprintId);
if (baseBlueprintId.equals(blueprintId)) {
try {
return getCount(_library.getLotroCardBlueprint(blueprintId));
} catch (CardNotFoundException exp) {
return 0;
}
}
return 0;
}
private int getCount(LotroCardBlueprint blueprint) {
final CardType cardType = blueprint.getCardType();
if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING)
return 1;
return 4;
}
@Override
public Map<String, Object> getExtraInformation() {
return Collections.emptyMap();
}
}

View File

@@ -1,25 +1,24 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.packs.PacksStorage;
import com.gempukku.lotro.packs.ProductLibrary;
import java.util.*;
public class DefaultCardCollection implements MutableCardCollection {
public static String CurrencyKey = "currency";
private final Map<String, Item> _counts = new LinkedHashMap<>();
private int _currency;
private Map<String, Object> _extraInformation = new HashMap<>();
public DefaultCardCollection() {
_extraInformation.put(CurrencyKey, 0);
}
public DefaultCardCollection(CardCollection cardCollection) {
this();
for (Item item : cardCollection.getAll()) {
_counts.put(item.getBlueprintId(), item);
}
_currency = cardCollection.getCurrency();
_extraInformation.putAll(cardCollection.getExtraInformation());
}
@@ -34,20 +33,23 @@ public class DefaultCardCollection implements MutableCardCollection {
@Override
public synchronized void addCurrency(int currency) {
_currency += currency;
int oldCurrency = (Integer) _extraInformation.get(CurrencyKey);
_extraInformation.put(CurrencyKey, oldCurrency + currency);
}
@Override
public synchronized boolean removeCurrency(int currency) {
if (_currency < currency)
int oldCurrency = (Integer) _extraInformation.get(CurrencyKey);
if (oldCurrency < currency)
return false;
_currency -= currency;
_extraInformation.put(CurrencyKey, oldCurrency - currency);
return true;
}
@Override
public synchronized int getCurrency() {
return _currency;
return (Integer) _extraInformation.get(CurrencyKey);
}
@Override

View File

@@ -1,8 +1,8 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.common.DBDefs;
import com.gempukku.lotro.db.GameHistoryDAO;
import com.gempukku.lotro.db.PlayerStatistic;
import com.gempukku.lotro.db.vo.GameHistoryEntry;
import java.util.Date;
import java.util.List;
@@ -36,15 +36,15 @@ public class GameHistoryService {
return count;
}
public List<GameHistoryEntry> getGameHistoryForPlayer(Player player, int start, int count) {
public List<DBDefs.GameHistory> getGameHistoryForPlayer(Player player, int start, int count) {
return _gameHistoryDAO.getGameHistoryForPlayer(player, start, count);
}
public List<GameHistoryEntry> getGameHistoryForFormat(String format, int count) {
public List<DBDefs.GameHistory> getGameHistoryForFormat(String format, int count) {
return _gameHistoryDAO.getGameHistoryForFormat(format, count);
}
public List<GameHistoryEntry> getTrackableGames(int count) {
public List<DBDefs.GameHistory> getTrackableGames(int count) {
return _gameHistoryDAO.getLastGames("Second Edition", count);
}

View File

@@ -296,11 +296,14 @@ public class GenericCardTestHelper extends AbstractAtTest {
public int GetFreepsArcheryTotal() { return RuleUtils.calculateFellowshipArcheryTotal(_game); }
public int GetShadowArcheryTotal() { return RuleUtils.calculateShadowArcheryTotal(_game); }
public int GetFreepsHandCount() { return GetPlayerHandCount(P1); }
public int GetShadowHandCount() { return GetPlayerHandCount(P2); }
public int GetPlayerHandCount(String player)
public int GetFreepsHandCount() { return GetFreepsHand().size(); }
public int GetShadowHandCount() { return GetShadowHand().size(); }
public List<? extends PhysicalCard> GetFreepsHand() { return GetPlayerHand(P1); }
public List<? extends PhysicalCard> GetShadowHand() { return GetPlayerHand(P2); }
public List<? extends PhysicalCard> GetPlayerHand(String player)
{
return _game.getGameState().getHand(player).size();
return _game.getGameState().getHand(player);
}
public int GetFreepsDeckCount() { return GetPlayerDeckCount(P1); }
@@ -421,6 +424,14 @@ public class GenericCardTestHelper extends AbstractAtTest {
});
}
public void FreepsDrawCard() {
_game.getGameState().playerDrawsCard(P1);
}
public void ShadowDrawCard() {
_game.getGameState().playerDrawsCard(P2);
}
public void FreepsShuffleCardsInDeck(String...cardNames) {
Arrays.stream(cardNames).forEach(cardName -> FreepsShuffleCardsInDeck(GetFreepsCard(cardName)));
}