mtg-decks-downloader

Tool to download Magic: The Gathering decklists from the Internet
git clone https://kevincorvisier.fr/git/mtg-decks-downloader.git
Log | Files | Refs | README

commit 58c9137229904c7fc98da0c2d61c2599942483e6
parent ce388cf45effc9fb5d7b5c613424e29ff2d73e9d
Author: Kevin Corvisier <git@kevincorvisier.fr>
Date:   Fri,  6 Jun 2025 04:59:25 +0900

Move MTGO file reading/writing to an external mtg-utils library
Diffstat:
Mpom.xml | 6++++++
Msrc/main/java/fr/kevincorvisier/mtg/dd/Cache.java | 12++++++------
Msrc/main/java/fr/kevincorvisier/mtg/dd/consumers/CardPoolConsumer.java | 7++++---
Msrc/main/java/fr/kevincorvisier/mtg/dd/consumers/DecklistConsumersService.java | 8++++----
Msrc/main/java/fr/kevincorvisier/mtg/dd/consumers/DefaultDecklistConsumer.java | 2+-
Msrc/main/java/fr/kevincorvisier/mtg/dd/model/Deck.java | 3++-
Dsrc/main/java/fr/kevincorvisier/mtg/dd/model/DeckContent.java | 11-----------
Dsrc/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileReader.java | 49-------------------------------------------------
Dsrc/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileWriter.java | 27---------------------------
Msrc/main/java/fr/kevincorvisier/mtg/dd/validation/DeckValidator.java | 5+++--
10 files changed, 26 insertions(+), 104 deletions(-)

diff --git a/pom.xml b/pom.xml @@ -42,6 +42,12 @@ <dependencies> <dependency> + <groupId>fr.kevincorvisier.mtg</groupId> + <artifactId>utils</artifactId> + <version>0.0.1-SNAPSHOT</version> + </dependency> + + <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/Cache.java b/src/main/java/fr/kevincorvisier/mtg/dd/Cache.java @@ -17,9 +17,9 @@ import org.apache.commons.io.output.StringBuilderWriter; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import fr.kevincorvisier.mtg.dd.model.DeckContent; -import fr.kevincorvisier.mtg.dd.mtgo.MagicOnlineFileReader; -import fr.kevincorvisier.mtg.dd.mtgo.MagicOnlineFileWriter; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineDeckContent; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineFileReader; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineFileWriter; import jakarta.validation.constraints.NotNull; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @@ -50,7 +50,7 @@ public class Cache } @Nullable - public DeckContent findByUrl(@NonNull @NotNull final URL url) + public MagicOnlineDeckContent findByUrl(@NonNull @NotNull final URL url) { final String content; @@ -72,7 +72,7 @@ public class Cache try (BufferedReader reader = new BufferedReader(new StringReader(content))) { - return new DeckContent(MagicOnlineFileReader.read(reader)); + return MagicOnlineFileReader.read(reader); } catch (final NumberFormatException | IOException e) { @@ -81,7 +81,7 @@ public class Cache } } - public void save(@NonNull @NotNull final URL url, @NonNull @NotNull final DeckContent content) throws SQLException, IOException + public void save(@NonNull @NotNull final URL url, @NonNull @NotNull final MagicOnlineDeckContent content) throws SQLException, IOException { final StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/consumers/CardPoolConsumer.java b/src/main/java/fr/kevincorvisier/mtg/dd/consumers/CardPoolConsumer.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; import fr.kevincorvisier.mtg.dd.model.Deck; import fr.kevincorvisier.mtg.dd.model.DeckMetadata; import fr.kevincorvisier.mtg.dd.validation.DeckValidator; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineDeckCard; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -38,10 +39,10 @@ public class CardPoolConsumer implements DecklistConsumer @Override public void consume(final Deck deck) { - for (final String cardName : deck.getContent().getMain().keySet()) + for (final MagicOnlineDeckCard card : deck.getContent().getMain().keySet()) { - if (validator.validateCard(cardName)) - cardPool.add(cardName); + if (validator.validateCard(card.getName())) + cardPool.add(card.getName()); } } diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/consumers/DecklistConsumersService.java b/src/main/java/fr/kevincorvisier/mtg/dd/consumers/DecklistConsumersService.java @@ -10,9 +10,9 @@ import org.springframework.stereotype.Service; import fr.kevincorvisier.mtg.dd.Cache; import fr.kevincorvisier.mtg.dd.Crawler; import fr.kevincorvisier.mtg.dd.model.Deck; -import fr.kevincorvisier.mtg.dd.model.DeckContent; import fr.kevincorvisier.mtg.dd.model.DeckMetadata; -import fr.kevincorvisier.mtg.dd.mtgo.MagicOnlineFileReader; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineDeckContent; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineFileReader; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -33,12 +33,12 @@ public class DecklistConsumersService if (acceptingConsumers.isEmpty()) return; - DeckContent content = cache.findByUrl(metadata.getUrl()); + MagicOnlineDeckContent content = cache.findByUrl(metadata.getUrl()); if (content == null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(crawler.openStream(metadata.getUrl())))) { - content = new DeckContent(MagicOnlineFileReader.read(reader)); + content = MagicOnlineFileReader.read(reader); cache.save(metadata.getUrl(), content); } catch (final Exception e) diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/consumers/DefaultDecklistConsumer.java b/src/main/java/fr/kevincorvisier/mtg/dd/consumers/DefaultDecklistConsumer.java @@ -23,8 +23,8 @@ import fr.kevincorvisier.mtg.dd.StopCondition; import fr.kevincorvisier.mtg.dd.model.Deck; import fr.kevincorvisier.mtg.dd.model.DeckComparator; import fr.kevincorvisier.mtg.dd.model.DeckMetadata; -import fr.kevincorvisier.mtg.dd.mtgo.MagicOnlineFileWriter; import fr.kevincorvisier.mtg.dd.validation.DeckValidator; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineFileWriter; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/model/Deck.java b/src/main/java/fr/kevincorvisier/mtg/dd/model/Deck.java @@ -1,5 +1,6 @@ package fr.kevincorvisier.mtg.dd.model; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineDeckContent; import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.NonNull; @@ -13,5 +14,5 @@ public class Deck @NonNull @NotNull - private final DeckContent content; + private final MagicOnlineDeckContent content; } diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/model/DeckContent.java b/src/main/java/fr/kevincorvisier/mtg/dd/model/DeckContent.java @@ -1,11 +0,0 @@ -package fr.kevincorvisier.mtg.dd.model; - -import java.util.Map; - -import lombok.Data; - -@Data -public class DeckContent -{ - private final Map<String, Integer> main; -} diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileReader.java b/src/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileReader.java @@ -1,49 +0,0 @@ -package fr.kevincorvisier.mtg.dd.mtgo; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PACKAGE) // static class -public class MagicOnlineFileReader -{ - private static final Pattern PATTERN_LINE = Pattern.compile("(?<count>\\d+) (?<name>.+)"); - - public static Map<String, Integer> read(final BufferedReader reader) throws NumberFormatException, IOException - { - final Map<String, Integer> result = new HashMap<>(); - - int emptyLineCount = 0; - String line; - while ((line = reader.readLine()) != null) - { - line = line.trim().replace(" // ", "/"); - if (line.isEmpty()) - { - emptyLineCount++; - continue; - } - - if (line.equals("Sideboard") || emptyLineCount == 2) // Skip the sideboard - break; - - emptyLineCount = 0; - - final Matcher matcher = PATTERN_LINE.matcher(line); - if (!matcher.matches()) - throw new RuntimeException("Cannot parse line: " + line); - - final String cardName = matcher.group("name"); - final int cardCount = Integer.parseInt(matcher.group("count")); - result.put(cardName, cardCount); - } - - return result; - } -} diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileWriter.java b/src/main/java/fr/kevincorvisier/mtg/dd/mtgo/MagicOnlineFileWriter.java @@ -1,27 +0,0 @@ -package fr.kevincorvisier.mtg.dd.mtgo; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.Map.Entry; - -import fr.kevincorvisier.mtg.dd.model.DeckContent; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PACKAGE) // static class -public class MagicOnlineFileWriter -{ - public static void write(final BufferedWriter writer, final DeckContent content) throws IOException - { - for (final Entry<String, Integer> card : content.getMain().entrySet()) - { - writer.append(Integer.toString(card.getValue())).append(' ').append(sanitizeCardName(card.getKey())).append('\n'); - } - } - - private static String sanitizeCardName(final String cardName) - { - final int indexOfSlash = cardName.indexOf("/"); - return indexOfSlash != -1 ? cardName.substring(0, indexOfSlash) : cardName; - } -} diff --git a/src/main/java/fr/kevincorvisier/mtg/dd/validation/DeckValidator.java b/src/main/java/fr/kevincorvisier/mtg/dd/validation/DeckValidator.java @@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import fr.kevincorvisier.mtg.dd.model.Deck; +import fr.kevincorvisier.mtg.utils.mtgo.MagicOnlineDeckCard; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -42,9 +43,9 @@ public class DeckValidator { int cardCount = 0; - for (final Entry<String, Integer> card : deck.getContent().getMain().entrySet()) + for (final Entry<MagicOnlineDeckCard, Integer> card : deck.getContent().getMain().entrySet()) { - final String cardName = card.getKey(); + final String cardName = card.getKey().getName(); if (!validateCard(cardName)) {