major: initial release

* initial development

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* pipeline

* ci/cd

* ci/cd

* ci/cd

* ci/cd

* ci/cd

* ci/cd

* ci/cd

* pokemon

* pokemon

* pokemon

* pokemon

* pokemon

* pokemon

* improvements

* improvements

* ci/cd

* ci/cd

* improvements

* improvements

* improvements

* improvements

* improvements

* improvements

* improvements

* improvements

* improvements

---------

Co-authored-by: sdine <sdine@sdine.com>
This commit is contained in:
Sebastian Dine
2026-05-09 11:05:47 +02:00
committed by GitHub
co-authored by sdine
parent 13262fa015
commit 55ace147bc
149 changed files with 12611 additions and 0 deletions
@@ -0,0 +1,30 @@
#pragma once
// ICardPreviewSource - resolves the preview image URL for a single card via
// the active game's external API. Implementations stay HTTP-bound, no UI deps.
//
// Modeled after per-game `getImage` helpers in
// `src/components/{magic,pokemon}/Selected*Panel.tsx`. The resulting URL is
// then fetched as raw image bytes by `CardPreviewService` and decoded by the
// UI layer (wxImage in our wx adapter).
#include "ccm/util/Result.hpp"
#include <string>
#include <string_view>
namespace ccm {
class ICardPreviewSource {
public:
virtual ~ICardPreviewSource() = default;
// Resolve the preview image URL for a single card. `setNo` is optional
// (empty string is fine); some game APIs (e.g. Pokemon TCG) can use it as
// a more precise lookup key, others (Magic/Scryfall) ignore it.
virtual Result<std::string> fetchImageUrl(std::string_view name,
std::string_view setId,
std::string_view setNo) = 0;
};
} // namespace ccm
@@ -0,0 +1,25 @@
#pragma once
// ICollectionRepository<T> - persistence port for a per-game card collection,
// keyed by uint32_t id. Mirrors the HashMap<u32, T> in the original Rust code.
#include "ccm/domain/Enums.hpp"
#include "ccm/util/Result.hpp"
#include <cstdint>
#include <map>
namespace ccm {
template <typename TCard>
class ICollectionRepository {
public:
using Map = std::map<std::uint32_t, TCard>;
virtual ~ICollectionRepository() = default;
virtual Result<Map> load(Game game) = 0;
virtual Result<void> save(Game game, const Map& collection) = 0;
};
} // namespace ccm
+33
View File
@@ -0,0 +1,33 @@
#pragma once
// IFileSystem - filesystem operations the services need, expressed as a
// narrow port. Real implementation is `StdFileSystem` (over <filesystem>).
// In-memory implementation can be plugged in for tests.
#include "ccm/util/Result.hpp"
#include <filesystem>
#include <string>
#include <vector>
namespace ccm {
class IFileSystem {
public:
virtual ~IFileSystem() = default;
[[nodiscard]] virtual bool exists(const std::filesystem::path& p) const = 0;
[[nodiscard]] virtual bool isDirectory(const std::filesystem::path& p) const = 0;
virtual Result<void> ensureDirectory(const std::filesystem::path& p) = 0;
virtual Result<std::string> readText(const std::filesystem::path& p) = 0;
virtual Result<void> writeText(const std::filesystem::path& p, std::string_view contents) = 0;
virtual Result<void> copyFile(const std::filesystem::path& from,
const std::filesystem::path& to,
bool overwrite) = 0;
virtual Result<void> remove(const std::filesystem::path& p) = 0;
virtual Result<std::vector<std::filesystem::path>> listDirectory(
const std::filesystem::path& p) = 0;
};
} // namespace ccm
+26
View File
@@ -0,0 +1,26 @@
#pragma once
// IHttpClient - tiny abstraction over HTTP GET so the rest of the codebase
// never sees libcurl/cpr directly. Tests can substitute a fake client.
#include "ccm/util/Result.hpp"
#include <string>
#include <string_view>
namespace ccm {
class IHttpClient {
public:
virtual ~IHttpClient() = default;
// Issue a blocking HTTPS GET. Returns the response body on success, an
// error string on failure (no exceptions across the port boundary).
//
// The returned `std::string` is a raw byte buffer - it is NOT decoded as
// text. Binary payloads (e.g. PNG/JPEG image bytes for the card preview
// feature) round-trip through this method intact.
virtual Result<std::string> get(std::string_view url) = 0;
};
} // namespace ccm
+34
View File
@@ -0,0 +1,34 @@
#pragma once
// IImageStore - manages card image files on disk inside the per-game
// `images/` subdirectory. Returns absolute paths so the UI can decode with
// whichever image library it likes (we use wxImage in the wx adapter); core
// stays free of any image decoding dependency.
#include "ccm/domain/Enums.hpp"
#include "ccm/util/Result.hpp"
#include <filesystem>
#include <string>
namespace ccm {
class IImageStore {
public:
virtual ~IImageStore() = default;
// Copy `srcPath` into the per-game image dir under filename `targetName`
// (extension preserved from `srcPath`). Returns the final filename
// (basename only, no path) on success.
virtual Result<std::string> copyIn(Game game,
const std::filesystem::path& srcPath,
const std::string& targetName) = 0;
// Delete `imageName` from the per-game image dir.
virtual Result<void> remove(Game game, const std::string& imageName) = 0;
// Resolve `imageName` to an absolute path inside the per-game image dir.
virtual std::filesystem::path resolvePath(Game game, const std::string& imageName) const = 0;
};
} // namespace ccm
+22
View File
@@ -0,0 +1,22 @@
#pragma once
// ISetRepository - persistence port for the cached `sets.json` of a game.
// Stored as a flat list to mirror the original Rust file layout.
#include "ccm/domain/Enums.hpp"
#include "ccm/domain/Set.hpp"
#include "ccm/util/Result.hpp"
#include <vector>
namespace ccm {
class ISetRepository {
public:
virtual ~ISetRepository() = default;
virtual Result<std::vector<Set>> load(Game game) = 0;
virtual Result<void> save(Game game, const std::vector<Set>& sets) = 0;
};
} // namespace ccm