.
This commit is contained in:
parent
0801ceee6a
commit
54ba7496c6
19 changed files with 1765 additions and 591 deletions
|
|
@ -151,15 +151,36 @@ using var httpClient = new HttpClient();
|
|||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Scry/1.0 (MTG Card Scanner - Database Generator)");
|
||||
|
||||
using var scryfallClient = new ScryfallClient(httpClient);
|
||||
using var db = new CardHashDatabase(outputDb);
|
||||
using var db = new CardDatabase(outputDb);
|
||||
|
||||
// Check existing database state
|
||||
var existingCardIds = await db.GetExistingCardIdsAsync();
|
||||
var existingCardNames = await db.GetExistingCardNamesAsync();
|
||||
var existingCount = await db.GetHashCountAsync();
|
||||
var existingOracleIds = await db.GetExistingOracleIdsAsync();
|
||||
var existingSetIds = await db.GetExistingSetIdsAsync();
|
||||
var existingCount = await db.GetCardCountAsync();
|
||||
var storedScryfallDate = await db.GetMetadataAsync("scryfall_updated_at");
|
||||
|
||||
Console.WriteLine($"Existing database has {existingCount} cards");
|
||||
Console.WriteLine($"Existing database has {existingCount} cards, {existingOracleIds.Count} oracles, {existingSetIds.Count} sets");
|
||||
|
||||
// Fetch all sets first
|
||||
Console.WriteLine("Fetching sets from Scryfall...");
|
||||
var scryfallSets = await scryfallClient.GetAllSetsAsync();
|
||||
var setsById = scryfallSets.ToDictionary(s => s.Id ?? "", s => s);
|
||||
var setsByCode = scryfallSets.ToDictionary(s => s.Code ?? "", s => s, StringComparer.OrdinalIgnoreCase);
|
||||
Console.WriteLine($"Found {scryfallSets.Count} sets");
|
||||
|
||||
// Insert any new sets
|
||||
var newSets = scryfallSets
|
||||
.Where(s => s.Id != null && !existingSetIds.Contains(s.Id))
|
||||
.Select(s => s.ToSet())
|
||||
.ToList();
|
||||
|
||||
if (newSets.Count > 0)
|
||||
{
|
||||
Console.WriteLine($"Inserting {newSets.Count} new sets...");
|
||||
await db.InsertSetBatchAsync(newSets);
|
||||
}
|
||||
|
||||
Console.WriteLine("Fetching bulk data info from Scryfall...");
|
||||
var bulkInfo = await scryfallClient.GetBulkDataInfoAsync("unique_artwork");
|
||||
|
|
@ -198,7 +219,8 @@ if (!needsUpdate)
|
|||
Console.WriteLine($"Downloading card data from: {bulkInfo.DownloadUri}");
|
||||
Console.WriteLine();
|
||||
|
||||
var newHashes = new List<CardHash>();
|
||||
var newCards = new List<Card>();
|
||||
var newOracles = new Dictionary<string, Oracle>();
|
||||
var processed = 0;
|
||||
var errors = 0;
|
||||
var skipped = 0;
|
||||
|
|
@ -209,10 +231,6 @@ var priorityNeeded = includeTestCards ? priorityCards.Count : 0;
|
|||
// Key: card name, Value: set code
|
||||
var foundPriorityWithSet = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Track deferred priority cards that might get a better set later
|
||||
// Key: card name, Value: list of (cardHash, setCode) candidates
|
||||
var deferredPriority = new Dictionary<string, List<(CardHash hash, string set)>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Helper to check if a set is preferred for a priority card
|
||||
bool IsPreferredSet(string cardName, string setCode)
|
||||
{
|
||||
|
|
@ -221,19 +239,21 @@ bool IsPreferredSet(string cardName, string setCode)
|
|||
return preferredSets.Length == 0 || preferredSets.Contains(setCode, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
await foreach (var card in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadUri))
|
||||
await foreach (var scryfallCard in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadUri))
|
||||
{
|
||||
// Skip non-English cards
|
||||
if (card.Lang != "en")
|
||||
if (scryfallCard.Lang != "en")
|
||||
continue;
|
||||
|
||||
var imageUri = card.GetImageUri("normal");
|
||||
var imageUri = scryfallCard.GetImageUri("normal");
|
||||
if (string.IsNullOrEmpty(imageUri))
|
||||
continue;
|
||||
|
||||
var cardId = card.Id ?? Guid.NewGuid().ToString();
|
||||
var cardName = card.Name ?? "Unknown";
|
||||
var setCode = card.Set ?? "???";
|
||||
var cardId = scryfallCard.Id ?? Guid.NewGuid().ToString();
|
||||
var cardName = scryfallCard.Name ?? "Unknown";
|
||||
var setCode = scryfallCard.Set ?? "???";
|
||||
var oracleId = scryfallCard.OracleId ?? cardId;
|
||||
var setId = scryfallCard.SetId ?? "";
|
||||
|
||||
// Check if this card already exists in the database
|
||||
if (existingCardIds.Contains(cardId))
|
||||
|
|
@ -262,7 +282,7 @@ await foreach (var card in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadU
|
|||
}
|
||||
|
||||
// Calculate how many slots we have left
|
||||
var totalCards = existingCount + newHashes.Count;
|
||||
var totalCards = existingCount + newCards.Count;
|
||||
var priorityRemaining = priorityNeeded - foundPriorityWithSet.Count;
|
||||
var slotsForNonPriority = maxCards - priorityRemaining;
|
||||
|
||||
|
|
@ -289,17 +309,15 @@ await foreach (var card in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadU
|
|||
using var preprocessed = ImagePreprocessor.ApplyClahe(bitmap);
|
||||
var hash = PerceptualHash.ComputeColorHash(preprocessed);
|
||||
|
||||
var cardHash = new CardHash
|
||||
{
|
||||
CardId = cardId,
|
||||
Name = cardName,
|
||||
SetCode = setCode,
|
||||
CollectorNumber = card.CollectorNumber,
|
||||
Hash = hash,
|
||||
ImageUri = imageUri
|
||||
};
|
||||
// Create Card (printing) with hash
|
||||
var card = scryfallCard.ToCard() with { Hash = hash };
|
||||
newCards.Add(card);
|
||||
|
||||
newHashes.Add(cardHash);
|
||||
// Track Oracle if we haven't seen it
|
||||
if (!existingOracleIds.Contains(oracleId) && !newOracles.ContainsKey(oracleId))
|
||||
{
|
||||
newOracles[oracleId] = scryfallCard.ToOracle();
|
||||
}
|
||||
|
||||
if (isPriorityCard)
|
||||
{
|
||||
|
|
@ -316,7 +334,7 @@ await foreach (var card in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadU
|
|||
|
||||
// Check if we have enough cards
|
||||
var foundAllPriority = foundPriorityWithSet.Count >= priorityNeeded;
|
||||
if (existingCount + newHashes.Count >= maxCards && foundAllPriority)
|
||||
if (existingCount + newCards.Count >= maxCards && foundAllPriority)
|
||||
{
|
||||
Console.WriteLine($"\nReached {maxCards} cards limit with all priority cards");
|
||||
break;
|
||||
|
|
@ -335,24 +353,37 @@ await foreach (var card in scryfallClient.StreamBulkDataAsync(bulkInfo.DownloadU
|
|||
Console.WriteLine();
|
||||
Console.WriteLine($"Skipped (already in DB): {skipped}");
|
||||
Console.WriteLine($"Newly processed: {processed} cards");
|
||||
Console.WriteLine($"New oracles: {newOracles.Count}");
|
||||
Console.WriteLine($"New priority cards found: {priorityFound}");
|
||||
Console.WriteLine($"Total priority cards: {foundPriorityWithSet.Count}/{priorityNeeded}");
|
||||
Console.WriteLine($"Errors: {errors}");
|
||||
Console.WriteLine();
|
||||
|
||||
if (newHashes.Count > 0)
|
||||
// Insert oracles first (cards reference them)
|
||||
if (newOracles.Count > 0)
|
||||
{
|
||||
Console.WriteLine($"Inserting {newHashes.Count} new hashes into database...");
|
||||
await db.InsertHashBatchAsync(newHashes);
|
||||
Console.WriteLine($"Inserting {newOracles.Count} new oracles...");
|
||||
await db.InsertOracleBatchAsync(newOracles.Values);
|
||||
}
|
||||
|
||||
if (newCards.Count > 0)
|
||||
{
|
||||
Console.WriteLine($"Inserting {newCards.Count} new cards...");
|
||||
await db.InsertCardBatchAsync(newCards);
|
||||
}
|
||||
|
||||
await db.SetMetadataAsync("generated_at", DateTime.UtcNow.ToString("O"));
|
||||
await db.SetMetadataAsync("scryfall_updated_at", scryfallDateStr);
|
||||
|
||||
var finalCount = await db.GetHashCountAsync();
|
||||
await db.SetMetadataAsync("card_count", finalCount.ToString());
|
||||
var finalCardCount = await db.GetCardCountAsync();
|
||||
var finalOracleCount = await db.GetOracleCountAsync();
|
||||
var finalSetCount = await db.GetSetCountAsync();
|
||||
|
||||
Console.WriteLine($"Database now has {finalCount} cards: {outputDb}");
|
||||
await db.SetMetadataAsync("card_count", finalCardCount.ToString());
|
||||
await db.SetMetadataAsync("oracle_count", finalOracleCount.ToString());
|
||||
await db.SetMetadataAsync("set_count", finalSetCount.ToString());
|
||||
|
||||
Console.WriteLine($"Database now has {finalCardCount} cards, {finalOracleCount} oracles, {finalSetCount} sets: {outputDb}");
|
||||
|
||||
// Report missing priority cards
|
||||
if (includeTestCards)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue