diff --git a/gemp-lotr/db/create-collection_entries.sql b/gemp-lotr/db/create-collection_entries.sql index cd4458df7..efff9d838 100644 --- a/gemp-lotr/db/create-collection_entries.sql +++ b/gemp-lotr/db/create-collection_entries.sql @@ -2,6 +2,10 @@ ALTER TABLE collection ADD CONSTRAINT fk_collection_player_id FOREIGN KEY (player_id) REFERENCES player(id); +ALTER TABLE collection ADD `extra_info` VARCHAR(5000) NULL; + +ALTER TABLE collection ADD CONSTRAINT uq_collection_player_type UNIQUE (player_id, type); + CREATE TABLE `collection_entries` ( `collection_id` int(11) NOT NULL, @@ -15,4 +19,27 @@ CREATE TABLE `collection_entries` ( `notes` varchar(100) DEFAULT NULL, PRIMARY KEY (`collection_id`, `product`), CONSTRAINT `collection_entries_ibfk_1` FOREIGN KEY (`collection_id`) REFERENCES `collection` (`id`) -) ; \ No newline at end of file +) ; + + +SELECT * +FROM collection c +WHERE player_id = 31040 + +SELECT * +FROM collection_entries +WHERE collection_id = 64643 + +SELECT * +FROM player p +LEFT JOIN collection c + ON c.player_id = p.id +WHERE c.id IS NULL +ORDER BY p.name + +SELECT count(*) +FROM collection_entries +GROUP BY collection_id + + + diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Booster Choice.pack b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)All Decipher Choice - Booster.pack similarity index 100% rename from gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Booster Choice.pack rename to gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)All Decipher Choice - Booster.pack diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Movie Booster Choice.pack b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Movie Choice - Booster.pack similarity index 100% rename from gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Movie Booster Choice.pack rename to gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)Movie Choice - Booster.pack diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)TSBoosterChoice.pack b/gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)TS Choice - Booster.pack similarity index 100% rename from gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)TSBoosterChoice.pack rename to gemp-lotr/gemp-lotr-cards/src/main/resources/product/old/(S)TS Choice - Booster.pack diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java index 212d48c0e..12e990a86 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java @@ -42,6 +42,13 @@ public class DBDefs { } + public static class Collection { + public int id; + public int player_id; + public String type; + public String extra_info; + } + public static class CollectionEntry { public int collection_id; public int quantity; @@ -53,4 +60,9 @@ public class DBDefs { public LocalDateTime modified_date; public String notes; } + + public static class Player { + public int id; + public String name; + } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedCollectionDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedCollectionDAO.java index 357d6905e..847466cff 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedCollectionDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/collection/CachedCollectionDAO.java @@ -1,6 +1,7 @@ package com.gempukku.lotro.collection; import com.gempukku.lotro.cache.Cached; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.db.CollectionDAO; import com.gempukku.lotro.game.CardCollection; import org.apache.commons.collections.map.LRUMap; @@ -8,6 +9,7 @@ import org.apache.commons.collections.map.LRUMap; import java.io.IOException; import java.sql.SQLException; import java.util.Collections; +import java.util.List; import java.util.Map; public class CachedCollectionDAO implements CollectionDAO, Cached { @@ -60,8 +62,13 @@ public class CachedCollectionDAO implements CollectionDAO, Cached { } @Override - public void addToCollection(int playerId, String type, CardCollection collection, String source) { - _delegate.addToCollection(playerId, type, collection, source); + public List getAllCollectionsForPlayer(int playerId) { + return _delegate.getAllCollectionsForPlayer(playerId); + } + + @Override + public void addToCollectionContents(int playerId, String type, CardCollection collection, String source) { + _delegate.addToCollectionContents(playerId, type, collection, source); String id = constructCacheKey(playerId, type); if(!_playerCollections.containsKey(id)) { _playerCollections.put(id, collection); @@ -73,7 +80,7 @@ public class CachedCollectionDAO implements CollectionDAO, Cached { } @Override - public void removeFromCollection(int playerId, String type, CardCollection collection, String source) { - _delegate.removeFromCollection(playerId, type, collection, source); + public void removeFromCollectionContents(int playerId, String type, CardCollection collection, String source) { + _delegate.removeFromCollectionContents(playerId, type, collection, source); } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java index 6e4949a36..d497aca06 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java @@ -1,6 +1,7 @@ package com.gempukku.lotro.db; import com.gempukku.lotro.cache.Cached; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.game.Player; import org.apache.commons.collections.map.LRUMap; @@ -132,6 +133,11 @@ public class CachedPlayerDAO implements PlayerDAO, Cached { _delegate.updateLastLoginIp(login, remoteAddr); } + @Override + public List getAllPlayers() { + return _delegate.getAllPlayers(); + } + @Override public boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException { boolean updated = _delegate.updateLastReward(player, previousReward, currentReward); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CollectionDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CollectionDAO.java index 518377edf..1d1be4a7c 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CollectionDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CollectionDAO.java @@ -1,9 +1,11 @@ package com.gempukku.lotro.db; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.game.CardCollection; import java.io.IOException; import java.sql.SQLException; +import java.util.List; import java.util.Map; public interface CollectionDAO { @@ -15,7 +17,9 @@ public interface CollectionDAO { void convertCollection(int playerId, String type) throws SQLException, IOException; - void addToCollection(int playerId, String type, CardCollection collection, String source); + List getAllCollectionsForPlayer(int playerId); - void removeFromCollection(int playerId, String type, CardCollection collection, String source); + void addToCollectionContents(int playerId, String type, CardCollection collection, String source); + + void removeFromCollectionContents(int playerId, String type, CardCollection collection, String source); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbCollectionDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbCollectionDAO.java index 6df5fd549..3e98abc64 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbCollectionDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbCollectionDAO.java @@ -1,7 +1,9 @@ package com.gempukku.lotro.db; import com.gempukku.lotro.collection.CollectionSerializer; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.game.CardCollection; +import org.json.simple.JSONObject; import org.sql2o.Query; import org.sql2o.Sql2o; @@ -11,6 +13,7 @@ import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.HashMap; +import java.util.List; import java.util.Map; public class DbCollectionDAO implements CollectionDAO { @@ -92,6 +95,30 @@ public class DbCollectionDAO implements CollectionDAO { public int ID; } + @Override + public List getAllCollectionsForPlayer(int playerId) { + + try { + Sql2o db = new Sql2o(_dbAccess.getDataSource()); + + try (org.sql2o.Connection conn = db.open()) { + String sql = """ + SELECT + id, player_id, type, extra_info + FROM collection + WHERE player_id = :playerID + """; + List result = conn.createQuery(sql) + .addParameter("playerID", playerId) + .executeAndFetch(DBDefs.Collection.class); + + return result; + } + } catch (Exception ex) { + throw new RuntimeException("Unable to retrieve collection types", ex); + } + } + public int getCollectionID(int playerId, String type) { try { @@ -119,45 +146,72 @@ public class DbCollectionDAO implements CollectionDAO { } } - public void updateCollection(int playerId, String type, CardCollection collection, String source) { + public void upsertCollection(int playerId, String type, CardCollection collection) { + String sql = """ + INSERT INTO collection(player_id, type, extra_info) + VALUES (:playerId, :type, :extraInfo) + ON DUPLICATE KEY UPDATE extra_info = :extraInfo; + """; + String json = ""; + try { + Sql2o db = new Sql2o(_dbAccess.getDataSource()); + + var jsonObj = new JSONObject(); + jsonObj.putAll(collection.getExtraInformation()); + json = jsonObj.toJSONString(); + + try (org.sql2o.Connection conn = db.beginTransaction()) { + Query query = conn.createQuery(sql, true); + query.addParameter("playerId", playerId) + .addParameter("type", type) + .addParameter("extraInfo", json); + query.executeUpdate(); + conn.commit(); + } + } catch (Exception ex) { + throw new RuntimeException("Unable to upsert collection", ex); + } + } + + public void updateCollectionContents(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); + updateCollectionContents(playerId, type, collection, source, sql, error); } - public void addToCollection(int playerId, String type, CardCollection collection, String source) { + public void addToCollectionContents(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); + updateCollectionContents(playerId, type, collection, source, sql, error); } - public void removeFromCollection(int playerId, String type, CardCollection collection, String source) { + public void removeFromCollectionContents(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); + updateCollectionContents(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"); + updateCollectionContents(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 + // + 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 @@ -165,7 +219,8 @@ public class DbCollectionDAO implements CollectionDAO { // - 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) { + private void updateCollectionContents(int playerId, String type, CardCollection collection, String source, String sql, String error) { + upsertCollection(playerId, type, collection); int collID = getCollectionID(playerId, type); try { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java index 2ec7a6833..5d83c6219 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java @@ -1,6 +1,8 @@ package com.gempukku.lotro.db; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.game.Player; +import org.sql2o.Sql2o; import java.security.MessageDigest; import java.sql.Connection; @@ -318,4 +320,23 @@ public class DbPlayerDAO implements PlayerDAO { } } } + + @Override + public List getAllPlayers() { + + try { + + Sql2o db = new Sql2o(_dbAccess.getDataSource()); + + try (org.sql2o.Connection conn = db.open()) { + String sql = "SELECT id, name FROM player"; + List result = conn.createQuery(sql) + .executeAndFetch(DBDefs.Player.class); + + return result; + } + } catch (Exception ex) { + throw new RuntimeException("Unable to retrieve players", ex); + } + } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java index dbf87fd46..1dfba9b15 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java @@ -1,5 +1,6 @@ package com.gempukku.lotro.db; +import com.gempukku.lotro.common.DBDefs; import com.gempukku.lotro.game.Player; import java.sql.SQLException; @@ -32,4 +33,6 @@ public interface PlayerDAO { public boolean registerUser(String login, String password, String remoteAddr) throws SQLException, LoginInvalidException; public void updateLastLoginIp(String login, String remoteAddr) throws SQLException; + + List getAllPlayers(); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java index 0bd770cda..51f32cd06 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/DefaultCardCollection.java @@ -22,8 +22,15 @@ public class DefaultCardCollection implements MutableCardCollection { _extraInformation.putAll(cardCollection.getExtraInformation()); } - public synchronized void setExtraInformation(Map extraInformation) { - _extraInformation = extraInformation; + public synchronized void setExtraInformation(Map extraInfo) { + _extraInformation.putAll(extraInfo); + //Some deserialization defaults to making the currency a Long rather than an Integer + if(extraInfo.containsKey(CurrencyKey)) { + var input = extraInfo.get(CurrencyKey); + if(input instanceof Long linput) { + _extraInformation.put(CurrencyKey, linput.intValue()); + } + } } @Override diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/CollectionSerializerTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/CollectionSerializerTest.java index c4a6b9c6a..bf1c02169 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/CollectionSerializerTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/CollectionSerializerTest.java @@ -74,7 +74,7 @@ public class CollectionSerializerTest { assertEquals(3, resultCollection.getItemCount("15_2")); assertEquals(3, resultCollection.getItemCount("15_4*")); assertEquals(2, resultCollection.getItemCount("FotR - Booster")); - assertEquals(1, resultCollection.getExtraInformation().size()); + assertEquals(2, resultCollection.getExtraInformation().size()); assertEquals("b", resultCollection.getExtraInformation().get("a")); } finally { IOUtils.closeQuietly(is); @@ -93,7 +93,8 @@ public class CollectionSerializerTest { assertEquals(12, resultCollection.getCurrency()); assertEquals(1, Iterables.size(resultCollection.getAll())); assertEquals(2, resultCollection.getItemCount("15_4*")); - assertEquals(1, resultCollection.getExtraInformation().size()); + //added entry + the default currency storage + assertEquals(2, resultCollection.getExtraInformation().size()); assertEquals("b", resultCollection.getExtraInformation().get("a")); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/NewCollectionManagerTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/NewCollectionManagerTests.java new file mode 100644 index 000000000..b4c69be96 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/collection/NewCollectionManagerTests.java @@ -0,0 +1,46 @@ +package com.gempukku.lotro.collection; + +import com.gempukku.lotro.db.DbAccess; +import com.gempukku.lotro.db.DbCollectionDAO; +import com.gempukku.lotro.db.DbPlayerDAO; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.io.IOException; +import java.sql.SQLException; + +// Tidings of Erebor +public class NewCollectionManagerTests +{ + private static DbAccess dbAccess = new DbAccess("jdbc:mysql://localhost:35001/gemp_db", + "root", "rootpass", false); + + @Test + public void ConvertCollectionTest() throws DecisionResultInvalidException, CardNotFoundException, IOException, SQLException { + var collDAO = new DbCollectionDAO(dbAccess, new CollectionSerializer()); + + collDAO.convertCollection(31040, "trophy"); + } + + @Test + public void ConvertAllPlayerCollectionsTest() throws DecisionResultInvalidException, CardNotFoundException, IOException, SQLException { + var collDAO = new DbCollectionDAO(dbAccess, new CollectionSerializer()); + var playerDAO = new DbPlayerDAO(dbAccess); + + var players = playerDAO.getAllPlayers(); + + for (var player : players) { + var collections = collDAO.getAllCollectionsForPlayer(player.id); + for(var coll : collections) { + collDAO.convertCollection(player.id, coll.type); + } + + } + + + } + + + +} \ No newline at end of file