commit 8a38d907e0c17456e5ea8e0a7247c82cfed64945 Author: Denis Denisov Date: Tue Nov 11 23:39:33 2025 +0300 Initial commit. Load list of cards via config (packs or single cards). diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b82ccd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/ +bin/ +obj/ diff --git a/ArkhamDBApi.cs b/ArkhamDBApi.cs new file mode 100644 index 0000000..425bb09 --- /dev/null +++ b/ArkhamDBApi.cs @@ -0,0 +1,42 @@ +using ArkhamPnP.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace ArkhamPnP +{ + internal class ArkhamDBApi + { + const string BASE_URL = "https://ru.arkhamdb.com/api/"; + + HttpClient http = new HttpClient(); + + public ArkhamDBApi() + { + } + + public async Task GetCard(string id) + { + var result = await http.GetAsync(BASE_URL + "public/card/" + id + ".json?_format=json"); + var content = await result.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + return new Card(doc.RootElement); + } + + public async Task> GetPack(string code) + { + var result = await http.GetAsync(BASE_URL + "public/cards/" + code + ".json?_format=json"); + var content = await result.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + var cards = new List(); + foreach (var item in doc.RootElement.EnumerateArray()) + { + cards.Add(new Card(item)); + } + return cards; + } + } +} diff --git a/ArkhamPnP.csproj b/ArkhamPnP.csproj new file mode 100644 index 0000000..4da1d92 --- /dev/null +++ b/ArkhamPnP.csproj @@ -0,0 +1,26 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + diff --git a/ArkhamPnP.sln b/ArkhamPnP.sln new file mode 100644 index 0000000..fef5d73 --- /dev/null +++ b/ArkhamPnP.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35707.178 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArkhamPnP", "ArkhamPnP.csproj", "{C61DC3E2-030A-44AE-84B5-50201E4EFDC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C61DC3E2-030A-44AE-84B5-50201E4EFDC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C61DC3E2-030A-44AE-84B5-50201E4EFDC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C61DC3E2-030A-44AE-84B5-50201E4EFDC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C61DC3E2-030A-44AE-84B5-50201E4EFDC0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ConfigLoader.cs b/ConfigLoader.cs new file mode 100644 index 0000000..20c7415 --- /dev/null +++ b/ConfigLoader.cs @@ -0,0 +1,49 @@ +using ArkhamPnP.Data; +using System.Text.Json; + +namespace ArkhamPnP +{ + internal class ConfigLoader + { + private string path; + + public ConfigLoader(string path) + { + this.path = path; + } + + public async Task> LoadCards() + { + var result = new List(); + var api = new ArkhamDBApi(); + var doc = LoadConfig(path); + foreach (var item in doc.RootElement.EnumerateArray()) + { + var type = item.GetProperty("type").GetString(); + if (type == "card") + { + result.Add(await api.GetCard(item.GetProperty("id").GetString())); + } + else if (type == "pack") + { + var pack = await api.GetPack(item.GetProperty("code").GetString()); + foreach (var c in pack) + { + if (c.IsPlayerCard) result.Add(c); + } + } + else + { + throw new Exception("Unknown config item type: " + type); + } + } + return result; + } + + JsonDocument LoadConfig(string path) + { + string configStr = File.ReadAllText(path); + return JsonDocument.Parse(configStr); + } + } +} diff --git a/Data/Card.cs b/Data/Card.cs new file mode 100644 index 0000000..c4d1bc6 --- /dev/null +++ b/Data/Card.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace ArkhamPnP.Data +{ + internal class Card + { + public string id; + public string pack_code; + public string pack_name; + public string text; + public string real_text; + public string image_src; + public string back_image_src; + public string type_code; + + public Card() + { + } + + public Card(JsonElement element) + { + this.id = element.GetProperty("code").GetString(); + pack_code = element.GetProperty("pack_code").GetString(); + pack_name = element.GetProperty("pack_name").GetString(); + text = Get(element, "text"); + real_text = Get(element, "real_text"); + image_src = element.GetProperty("imagesrc").GetString(); + back_image_src = Get(element, "backimagesrc"); + type_code = element.GetProperty("type_code").GetString(); + } + + private string Get(JsonElement element, string v) + { + if (element.TryGetProperty(v, out var p)) + { + return p.GetString(); + } + return ""; + } + + public bool IsPlayerCard + { + get + { + return type_code == "asset" || type_code == "event" || type_code == "skill"; + } + } + } +} diff --git a/Images/encounter.png b/Images/encounter.png new file mode 100644 index 0000000..97cf142 Binary files /dev/null and b/Images/encounter.png differ diff --git a/Images/player.png b/Images/player.png new file mode 100644 index 0000000..8144a21 Binary files /dev/null and b/Images/player.png differ diff --git a/PDFComposer.cs b/PDFComposer.cs new file mode 100644 index 0000000..e639bf4 --- /dev/null +++ b/PDFComposer.cs @@ -0,0 +1,37 @@ +using ArkhamPnP.Data; +using iText.Kernel.Pdf; +using iText.Layout; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.Xml; +using System.Text; +using System.Threading.Tasks; + +namespace ArkhamPnP +{ + internal class PDFComposer + { + const float PAGE_WIDTH = 210; // mm + const float PAGE_HEIGHT = 297; // mm + const float CARD_WIDTH = 63; // mm + const float CARD_HEIGHT = 89; // mm + const float FRONT_PADDING = 3; // mm + const float MARGIN_SIDE = 5; // mm + const float MARGIN_TOP_BOTTOM = 5; // mm + + public void PrintCards(List cards, string destinationPath) + { + var pdfDoc = new PdfDocument(new PdfWriter(destinationPath)); + var doc = new Document(pdfDoc, new iText.Kernel.Geom.PageSize(PAGE_WIDTH, PAGE_HEIGHT)); + // compute card amount on page + int grid_width = 0; + while (CARD_WIDTH * (grid_width + 1) + FRONT_PADDING * (grid_width + 1 - 1) + + 2 * MARGIN_SIDE <= PAGE_WIDTH) grid_width++; + int grid_height = 0; + while (CARD_HEIGHT * (grid_height + 1) + FRONT_PADDING * (grid_height + 1 - 1) + + 2 * MARGIN_TOP_BOTTOM <= PAGE_HEIGHT) grid_height++; + Console.WriteLine("Will produce grid of cards " + grid_height + "x" + grid_width); + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..1d25eea --- /dev/null +++ b/Program.cs @@ -0,0 +1,21 @@ +// See https://aka.ms/new-console-template for more information +using ArkhamPnP; + +if (args.Length < 2) +{ + Console.WriteLine("Usage: ArkhamPnP "); + return 0; +} +var loader = new ConfigLoader(args[0]); +var cards = await loader.LoadCards(); + +Console.WriteLine("Loaded cards:"); +foreach (var card in cards) +{ + Console.WriteLine($"ID: {card.id} front: {card.image_src} back: {card.back_image_src}"); +} +var composer = new PDFComposer(); +composer.PrintCards(cards, args[1]); + + +return 0; \ No newline at end of file