mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-09-04 17:23:29 +00:00
set completion pokemon
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// PokemonCardPreviewSource: ICardPreviewSource implementation for the Pokemon
|
||||
// TCG. Calls the Pokemon TCG search endpoint at
|
||||
// https://api.pokemontcg.io/v2/cards?q=name:"<name>" set.id:<setId> number:<setNo>
|
||||
// and returns `data[0].images.large` (with `images.small` as a graceful
|
||||
// fallback). Mirrors the established `getImage` flow in
|
||||
// `src/components/pokemon/SelectedPokemonPanel.tsx`.
|
||||
// TCG. When set id + collector number are both known, prefers
|
||||
// GET https://api.pokemontcg.io/v2/cards/{setId}-{number}
|
||||
// then falls back to a name-less search `set.id:… number:…`. Name-based
|
||||
// search is kept for lookups that lack a set number (or set id). Returns
|
||||
// `images.large` (with `images.small` as a graceful fallback).
|
||||
|
||||
#include "ccm/ports/ICardPreviewSource.hpp"
|
||||
#include "ccm/ports/IHttpClient.hpp"
|
||||
@@ -32,24 +32,37 @@ public:
|
||||
std::string_view setId) override;
|
||||
|
||||
// Build the fully URL-encoded Pokemon TCG search URL for the given card.
|
||||
// When both setId and setNo are non-empty, omits the name: clause so the
|
||||
// Lucene query cannot miss on name∩number intersections.
|
||||
// Exposed for unit testing and to keep encoding rules in one place.
|
||||
static std::string buildSearchUrl(std::string_view name,
|
||||
std::string_view setId,
|
||||
std::string_view setNo);
|
||||
|
||||
// Direct card endpoint: /v2/cards/{setId}-{normalizedNumber}.
|
||||
static std::string buildCardByIdUrl(std::string_view setId, std::string_view setNo);
|
||||
|
||||
// Strip everything after the first '/' (e.g. "4/102" -> "4"). Used by
|
||||
// preview lookups, auto-detect, and set-completion ownership matching.
|
||||
static std::string normalizeCollectorNumber(std::string_view setNo);
|
||||
|
||||
// Slimmer search URL for auto-detect: omits the number clause and asks the
|
||||
// API for only the fields the print-variant parser needs.
|
||||
static std::string buildDetectSearchUrl(std::string_view name,
|
||||
std::string_view setId);
|
||||
|
||||
// Parse a Pokemon TCG /v2/cards response body and pull out the image URL
|
||||
// for the first matching card. Prefers `images.large`, falls back to
|
||||
// `images.small`. Errors are classified:
|
||||
// Parse a Pokemon TCG /v2/cards *search* response body (`data` array) and
|
||||
// pull out the image URL for the first matching card. Prefers
|
||||
// `images.large`, falls back to `images.small`. Errors are classified:
|
||||
// - JSON parse failure or missing/non-array `data` => Transient.
|
||||
// - Empty `data` array or missing image variants => NotFound.
|
||||
static Result<std::string, PreviewLookupError>
|
||||
parseResponse(const std::string& body);
|
||||
|
||||
// Parse a Pokemon TCG /v2/cards/{id} response (`data` object).
|
||||
static Result<std::string, PreviewLookupError>
|
||||
parseCardByIdResponse(const std::string& body);
|
||||
|
||||
// Enumerate distinct collector numbers (and rarities) for an exact card
|
||||
// name inside the chosen set. Exposed for unit testing without HTTP.
|
||||
static Result<std::vector<AutoDetectedPrint>>
|
||||
|
||||
@@ -6,23 +6,56 @@
|
||||
// The Pokemon TCG API already returns `releaseDate` in `YYYY/MM/DD` format,
|
||||
// so no rewriting is needed (unlike Scryfall's `released_at`).
|
||||
// Behavior matches `pokemon/set_services.rs::update_sets`.
|
||||
// Set-completion catalog is built from a paginated /v2/cards dump.
|
||||
|
||||
#include "ccm/domain/PokemonSetCatalog.hpp"
|
||||
#include "ccm/domain/Set.hpp"
|
||||
#include "ccm/games/IGameModule.hpp"
|
||||
#include "ccm/ports/IHttpClient.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ccm {
|
||||
|
||||
class PokemonSetSource final : public ISetSource {
|
||||
public:
|
||||
static constexpr const char* kEndpoint = "https://api.pokemontcg.io/v2/sets";
|
||||
static constexpr const char* kCardsEndpoint = "https://api.pokemontcg.io/v2/cards";
|
||||
static constexpr int kCardsPageSize = 250;
|
||||
|
||||
struct FetchWithCatalog {
|
||||
std::vector<Set> sets;
|
||||
PokemonSetCatalog catalog;
|
||||
};
|
||||
|
||||
explicit PokemonSetSource(IHttpClient& http);
|
||||
|
||||
Result<std::vector<Set>> fetchAll() override;
|
||||
|
||||
// Sets endpoint + paginated cards dump for the offline checklist.
|
||||
Result<FetchWithCatalog> fetchAllWithCatalog();
|
||||
|
||||
// Pure parser exposed for unit testing without a network round-trip.
|
||||
static Result<std::vector<Set>> parseResponse(const std::string& body);
|
||||
|
||||
// Build / merge checklist packs from one /v2/cards page body. Pass an
|
||||
// accumulating catalog; returns page count metadata for pagination.
|
||||
struct CardsPageMeta {
|
||||
int page{1};
|
||||
int pageSize{kCardsPageSize};
|
||||
int count{0};
|
||||
int totalCount{0};
|
||||
};
|
||||
static Result<CardsPageMeta> mergeCardsPage(const std::string& body,
|
||||
PokemonSetCatalog& catalog,
|
||||
const std::vector<Set>& sets);
|
||||
|
||||
static Result<PokemonSetCatalog> parseCatalog(const std::string& body,
|
||||
const std::vector<Set>& sets);
|
||||
|
||||
static std::string buildCardsPageUrl(int page, int pageSize = kCardsPageSize);
|
||||
|
||||
private:
|
||||
IHttpClient& http_;
|
||||
};
|
||||
|
||||
@@ -54,6 +54,10 @@ public:
|
||||
|
||||
[[nodiscard]] bool hasPrintsForSet(std::string_view setId) const noexcept;
|
||||
|
||||
// All prints for a set (catalog gap-fill / set-completion checklists).
|
||||
[[nodiscard]] std::vector<JapanesePokemonPrintEnInfo>
|
||||
printsForSet(std::string_view setId) const;
|
||||
|
||||
// TCGPlayer product-image CDN URL for classic JA gap-fill.
|
||||
[[nodiscard]] static std::string tcgplayerImageUrl(std::string_view productId);
|
||||
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
// JapanesePokemonSetSource: TCGdex ja set list + per-set detail for release
|
||||
// dates. English display names come from JapanesePokemonEnCatalog when present.
|
||||
// dates and set-completion checklists. English display names come from
|
||||
// JapanesePokemonEnCatalog when present.
|
||||
|
||||
#include "ccm/domain/PokemonSetCatalog.hpp"
|
||||
#include "ccm/domain/Set.hpp"
|
||||
#include "ccm/games/IGameModule.hpp"
|
||||
#include "ccm/games/pokemonjp/JapanesePokemonEnCatalog.hpp"
|
||||
#include "ccm/ports/IHttpClient.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace ccm {
|
||||
|
||||
class JapanesePokemonSetSource final : public ISetSource {
|
||||
public:
|
||||
static constexpr const char* kListEndpoint = "https://api.tcgdex.net/v2/ja/sets";
|
||||
|
||||
struct FetchWithCatalog {
|
||||
std::vector<Set> sets;
|
||||
PokemonSetCatalog catalog;
|
||||
};
|
||||
|
||||
JapanesePokemonSetSource(IHttpClient& http, const JapanesePokemonEnCatalog& catalog);
|
||||
|
||||
Result<std::vector<Set>> fetchAll() override;
|
||||
|
||||
// List + per-set detail (cards + release date) + EN catalog gap-fill.
|
||||
Result<FetchWithCatalog> fetchAllWithCatalog();
|
||||
|
||||
void augmentCachedSets(std::vector<Set>& sets) const override;
|
||||
|
||||
// Pure parsers for hermetic tests.
|
||||
@@ -28,6 +43,16 @@ public:
|
||||
static std::string rewriteReleaseDate(std::string_view isoDate);
|
||||
static std::string buildSetDetailUrl(std::string_view setId);
|
||||
|
||||
// Build one pack checklist from a set-detail body, then gap-fill from catalog.
|
||||
static Result<PokemonSetCatalogPack> parseCatalogPackFromSetDetail(
|
||||
const std::string& detailBody,
|
||||
const Set& set,
|
||||
const JapanesePokemonEnCatalog& enCatalog);
|
||||
|
||||
// Catalog-only pack (classic products with no TCGdex detail).
|
||||
static PokemonSetCatalogPack catalogPackFromEnCatalog(
|
||||
const Set& set, const JapanesePokemonEnCatalog& enCatalog);
|
||||
|
||||
// Original-era theme decks / sheets omitted by TCGdex JA. Idempotent by id.
|
||||
static void appendMissingClassicProducts(std::vector<Set>& sets);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user