#pragma once // IGameModule + ISetSource: the seam that lets the UI handle Magic and Pokemon // uniformly. New game support is "implement these interfaces and register the // module in the composition root" - see the Rust `templates/` module for the // pattern this is modeled after. #include "ccm/domain/Enums.hpp" #include "ccm/domain/Set.hpp" #include "ccm/ports/ICardPreviewSource.hpp" #include "ccm/util/Result.hpp" #include #include namespace ccm { class ISetSource { public: virtual ~ISetSource() = default; // Fetch the canonical set list from the game's external API. // Implementations return a vector that has already been filtered // (e.g. no digital-only sets) and sorted by release date ascending. virtual Result> fetchAll() = 0; // Optional post-process for locally cached set lists (e.g. inject products // the upstream API omits). Default is a no-op. Called by SetService::getSets. virtual void augmentCachedSets(std::vector& /*sets*/) const {} }; class IGameModule { public: virtual ~IGameModule() = default; [[nodiscard]] virtual Game id() const noexcept = 0; // Subdirectory name used inside the data storage root. Matches the Rust // string literals "magic" / "pokemon". [[nodiscard]] virtual std::string dirName() const = 0; [[nodiscard]] virtual std::string displayName() const = 0; virtual ISetSource& setSource() = 0; // Optional preview source. Returning nullptr signals the game has no // remote preview API (the UI then renders only locally stored images). // The default keeps existing modules compiling without forcing every // game to provide one. virtual ICardPreviewSource* cardPreviewSource() noexcept { return nullptr; } }; } // namespace ccm