mtg-lets-trade

Website/webapp to facilitate trading between players of Magic: The Gathering
git clone https://kevincorvisier.fr/git/mtg-lets-trade.git
Log | Files | Refs

commit 27dd51bc6bfe215a9bb73a8bdef22e202deb227a
parent da423c009c81d1952f49a62cd329388e68d757b8
Author: Kevin Corvisier <git@kevincorvisier.fr>
Date:   Thu, 20 Mar 2025 13:45:01 +0900

Have different DBPrintedCard for each finish of scryfall cards

Diffstat:
Asrc/main/java/fr/kevincorvisier/mtg/letstrade/database/CardFinish.java | 8++++++++
Msrc/main/java/fr/kevincorvisier/mtg/letstrade/database/entities/DBPrintedCard.java | 14++++++++++----
Msrc/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/ScryfallRestClient.java | 3+++
Msrc/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/domain/ScryfallCard.java | 4++++
Msrc/main/java/fr/kevincorvisier/mtg/letstrade/tasks/ScryfallSynchronizationTask.java | 63+++++++++++++++++++++++++++++++++++++++++----------------------
5 files changed, 66 insertions(+), 26 deletions(-)

diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/database/CardFinish.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/database/CardFinish.java @@ -0,0 +1,8 @@ +package fr.kevincorvisier.mtg.letstrade.database; + +public enum CardFinish +{ + NONFOIL, + FOIL, + ETCHED +} diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/database/entities/DBPrintedCard.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/database/entities/DBPrintedCard.java @@ -2,14 +2,15 @@ package fr.kevincorvisier.mtg.letstrade.database.entities; import java.util.UUID; -import org.hibernate.annotations.NaturalId; - +import fr.kevincorvisier.mtg.letstrade.database.CardFinish; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import jakarta.persistence.Version; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; @@ -20,6 +21,7 @@ import lombok.NoArgsConstructor; import lombok.NonNull; @Entity(name = "card") +@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "scryfallId", "finish" }) }) @Data @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -40,8 +42,7 @@ public class DBPrintedCard */ @NonNull @NotNull - @NaturalId - @Column(updatable = false, nullable = false, unique = true) + @Column(updatable = false, nullable = false) private UUID scryfallId; @NonNull @@ -62,6 +63,11 @@ public class DBPrintedCard @Column(nullable = false) private String lang; + @NonNull + @NotNull + @Column(nullable = false) + private CardFinish finish; + /** * This card’s collector number. Note that collector numbers can contain non-numeric characters, such as letters or ★. */ diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/ScryfallRestClient.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/ScryfallRestClient.java @@ -114,6 +114,9 @@ public class ScryfallRestClient case "games": builder.games(readArray(jParser)); break; + case "finishes": + builder.finishes(readArray(jParser)); + break; case "promo_types": builder.promoTypes(readArray(jParser)); break; diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/domain/ScryfallCard.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/scryfall/domain/ScryfallCard.java @@ -44,6 +44,10 @@ public class ScryfallCard @NotNull private Collection<String> games; + @NonNull + @NotNull + private Collection<@NotNull String> finishes; + /** * This card’s set code. */ diff --git a/src/main/java/fr/kevincorvisier/mtg/letstrade/tasks/ScryfallSynchronizationTask.java b/src/main/java/fr/kevincorvisier/mtg/letstrade/tasks/ScryfallSynchronizationTask.java @@ -7,15 +7,13 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.scheduling.concurrent.CustomizableThreadFactory; import org.springframework.stereotype.Component; +import fr.kevincorvisier.mtg.letstrade.database.CardFinish; import fr.kevincorvisier.mtg.letstrade.database.entities.DBOracleCard; import fr.kevincorvisier.mtg.letstrade.database.entities.DBOracleCard.DBOracleCardBuilder; import fr.kevincorvisier.mtg.letstrade.database.entities.DBPrintedCard; @@ -28,6 +26,7 @@ import fr.kevincorvisier.mtg.letstrade.database.repositories.DBSetRepository; import fr.kevincorvisier.mtg.letstrade.scryfall.ScryfallRestClient; import fr.kevincorvisier.mtg.letstrade.scryfall.domain.ScryfallCard; import jakarta.validation.constraints.NotNull; +import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -36,7 +35,6 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class ScryfallSynchronizationTask { - private final ExecutorService executorService = Executors.newSingleThreadExecutor(new CustomizableThreadFactory("scryfall-synchronization-thread-")); private final DBOracleCardRepository oracleCardRepository; private final DBSetRepository setRepository; private final DBCardRepository cardRepository; @@ -95,11 +93,9 @@ public class ScryfallSynchronizationTask private void saveCards(final Iterable<ScryfallCard> cards) { - executorService.execute(() -> { - final Map<UUID, DBOracleCard> oracleCards = saveOracleCards(cards); - final Map<UUID, DBSet> sets = saveSets(cards); - savePrintedCards(cards, oracleCards, sets); - }); + final Map<UUID, DBOracleCard> oracleCards = saveOracleCards(cards); + final Map<UUID, DBSet> sets = saveSets(cards); + savePrintedCards(cards, oracleCards, sets); } @NotNull @@ -175,9 +171,9 @@ public class ScryfallSynchronizationTask for (final ScryfallCard card : cards) scryfallIds.add(card.getId()); - final Map<UUID, DBPrintedCard> existingByScryfallId = new HashMap<>(); + final Map<DBPrintedCardMergeKey, DBPrintedCard> existingByScryfallId = new HashMap<>(); for (final DBPrintedCard card : cardRepository.findAllByScryfallIdIn(scryfallIds)) - existingByScryfallId.put(card.getScryfallId(), card); + existingByScryfallId.put(new DBPrintedCardMergeKey(card), card); final Collection<DBPrintedCard> toSave = new HashSet<>(); @@ -204,20 +200,43 @@ public class ScryfallSynchronizationTask continue; } - final DBPrintedCard existing = existingByScryfallId.get(card.getId()); - final DBPrintedCardBuilder builder = existing != null ? existing.toBuilder() : DBPrintedCard.builder().scryfallId(card.getId()); + for (final String finish : card.getFinishes()) + { + final CardFinish finish2 = CardFinish.valueOf(finish.toUpperCase()); - builder.oracleCard(oracleCard); - builder.lang(card.getLang()); - builder.set(set); - builder.collectorNumber(card.getCollectorNumber()); - final DBPrintedCard updated = builder.build(); + final DBPrintedCard existing = existingByScryfallId.get(new DBPrintedCardMergeKey(card, finish2)); + final DBPrintedCardBuilder builder = existing != null ? existing.toBuilder() : DBPrintedCard.builder().scryfallId(card.getId()).finish(finish2); - if (existing == null || !existing.equals(updated)) - toSave.add(updated); + builder.oracleCard(oracleCard); + builder.lang(card.getLang()); + builder.set(set); + builder.collectorNumber(card.getCollectorNumber()); + final DBPrintedCard updated = builder.build(); + + if (existing == null || !existing.equals(updated)) + toSave.add(updated); + } + } + + cardRepository.saveAll(toSave); + } + + @Data + private class DBPrintedCardMergeKey + { + private final UUID scryfallId; + private final CardFinish finish; + + public DBPrintedCardMergeKey(final ScryfallCard card, final CardFinish finish) + { + this.scryfallId = card.getId(); + this.finish = finish; } - for (final DBPrintedCard card : cardRepository.saveAll(toSave)) - existingByScryfallId.put(card.getScryfallId(), card); + public DBPrintedCardMergeKey(final DBPrintedCard card) + { + this.scryfallId = card.getScryfallId(); + this.finish = card.getFinish(); + } } }