Better handling of long cards (mostly by removing redundant information)

This commit is contained in:
Lumen Keyes 2024-08-19 15:49:28 -06:00
parent 5ad5b2edf3
commit d81d19c1f6
6 changed files with 959 additions and 1715 deletions

View File

@ -0,0 +1,100 @@
1 Ancestral Recall (VMA) 1
1 Arid Mesa (MH2) 436 *E*
1 Boseiju, Who Endures (NEO) 266
1 Botanical Sanctum (KLD) 244
1 Brainstorm (MMQ) 61
1 Breeding Pool (RNA) 246
1 Consider (MID) 44
1 Cosmic Rebirth (MAT) 78 *F*
1 Counterspell (MMQ) 69
1 Cryptic Command (MMA) 38
1 Deserted Beach (WHO) 270
1 Dovin's Veto (TSR) 375
1 Dreamroot Cascade (VOW) 262
1 Dress Down (MH2) 39
1 Eiganjo, Seat of the Empire (NEO) 268
1 Entreat the Angels (AVR) 20
1 Field of the Dead (M20) 247
1 Flooded Strand (MH3) 220
1 Force of Negation (H1R) 9 *F*
1 Force of Will (ME1) 33
1 Get Lost (LCI) 333
1 Gideon Jura (ROE) 21
1 Gitaxian Probe (NPH) 35
1 Growth Spiral (RNA) 178
1 Hallowed Fountain (RTR) 241
1 Hedge Maze (MKM) 326 *F*
1 Ice-Fang Coatl (H1R) 27 *F*
1 Island (MMQ) 335 *F*
1 Jace, the Mind Sculptor (EMA) 57
1 Karakas (TD0) B32
1 Leyline Binding (PRM) 103396
1 Library of Alexandria (ARN) 76
1 Logic Knot (FUT) 52
1 Lose Focus (MH2) 49
1 Lush Portico (MKM) 327
1 Mana Leak (PLST) DDN-64
1 Marsh Flats (MH2) 437 *E*
1 Mental Misstep (NPH) 38
1 Mental Note (JUD) 46
1 Merchant Scroll (8ED) 91
1 Meticulous Archive (MKM) 328 *F*
1 Misty Rainforest (MH2) 250
1 Murktide Regent (MH2) 337 *F*
1 Mystic Sanctuary (ELD) 247
1 Mystical Tutor (MIR) 80
1 No More Lies (MKM) 221
1 Oko, Thief of Crowns (ELD) 197
1 Opt (STA) 19
1 Otawara, Soaring City (NEO) 271
1 Path to Exile (PF20) 1 *F*
1 Plains (INV) 331 *F*
1 Planar Genesis (MH3) 198
1 Polluted Delta (MH3) 224
1 Ponder (C21) 125
1 Portent (ICE) 90
1 Preordain (CMR) 84
1 Prismatic Ending (MH2) 384
1 Prismatic Vista (H1R) 40 *E*
1 Remand (RVR) 59
1 Reprieve (LTR) 26
1 Savannah (LEA) 280
1 Scalding Tarn (ZNE) 7
1 Scapeshift (M19) 201
1 Seachrome Coast (ONE) 258
1 Seasoned Dungeoneer (CLB) 610
1 Sensei's Divining Top (CHK) 268
1 Serum Visions (5DN) 36
1 Shark Typhoon (IKO) 67
1 Sleight of Hand (P02) 46
1 Snapcaster Mage (ISD) 78
1 Snow-Covered Forest (KHM) 285
1 Snow-Covered Island (ICE) 371
1 Snow-Covered Plains (ICE) 367
1 Solitude (MH2) 307 *F*
1 Spara's Headquarters (SNC) 257
1 Spell Pierce (SLD) 41
1 Spell Snare (DIS) 33
1 Supreme Verdict (RTR) 201
1 Swords to Plowshares (ICE) 54
1 Tamiyo, Inquisitive Student // Tamiyo, Seasoned Scholar (MH3) 443
1 Teferi, Hero of Dominaria (DOM) 207
1 Teferi, Time Raveler (WAR) 221
1 Temple Garden (RAV) 284
1 Terminus (AVR) 38
1 The One Ring (LTR) 451
1 Thought Scour (2X2) 351
1 Treasure Cruise (TSR) 319
1 Triumph of Saint Katherine (40K) 17
1 Tropical Island (LEA) 283
1 Tundra (LEA) 284
1 Underground Sea (SUM) 290
1 Up the Beanstalk (WOE) 195
1 Uro, Titan of Nature's Wrath (PTHB) 229p
1 Verdant Catacombs (MH2) 440 *E*
1 Wall of Blossoms (STH) 125
1 Wall of Omens (2X2) 344
1 Wasteland (SLD) 178
1 White Plume Adventurer (CLB) 558 *F*
1 Windswept Heath (KTK) 248
1 Wooded Foothills (ONS) 330

View File

@ -0,0 +1,98 @@
1 Adarkar Wastes (DMU) 377 *F*
1 Ajani, Nacatl Pariah // Ajani, Nacatl Avenger (MH3) 237
1 Arid Mesa (MH2) 436 *E*
1 Bloodstained Mire (MH3) 216
1 Bonecrusher Giant // Stomp (ELD) 115
1 Brainstorm (MMQ) 61
1 Brazen Borrower // Petty Theft (ELD) 39
1 Caves of Chaos Adventurer (CLB) 167
1 Chain Lightning (JMP) 302
1 Comet, Stellar Pup (UNF) 166
1 Consider (MID) 44
1 Counterspell (MMQ) 69
1 Daze (EMA) 44
1 Dragon's Rage Channeler (MH2) 121
1 Dreadhorde Arcanist (WAR) 125
1 Eiganjo, Seat of the Empire (NEO) 268
1 Expressive Iteration (SPG) 43
1 Fable of the Mirror-Breaker // Reflection of Kiki-Jiki (NEO) 141
1 Fiery Islet (WHO) 278
1 Flame Slash (ROE) 145
1 Flooded Strand (MH3) 220
1 Force of Negation (H1R) 9 *F*
1 Force of Will (VMA) 69
1 Forked Bolt (ROE) 146
1 Forth Eorlingas! (LTC) 139
1 Fury (MH2) 126
1 Galvanic Discharge (MH3) 122 *F*
1 Geist of Saint Traft (ISD) 213
1 Get Lost (LCI) 333
1 Ghostfire Slice (MH3) 123
1 Gitaxian Probe (NPH) 35
1 Gush (MMQ) 82
1 Hallowed Fountain (RTR) 241
1 Inspiring Vantage (OTJ) 269 *F*
3 Island (MMQ) 335 *F*
1 Karakas (TD0) B32
1 Ledger Shredder (SNC) 46
1 Lightning Angel (APC) 108
1 Lightning Bolt (4ED) 208
1 Lightning Helix (MKM) 218 *F*
1 Lórien Revealed (LTR) 60
1 Mana Leak (8ED) 89
1 Mantis Rider (KTK) 184
1 Marsh Flats (MH2) 437 *E*
1 Memory Lapse (STA) 16 *F*
1 Mental Misstep (NPH) 38
1 Mental Note (JUD) 46
1 Meticulous Archive (MKM) 328 *F*
1 Misty Rainforest (MH2) 250
1 Mountain (MMQ) 346 *F*
1 Mox Pearl (VMA) 7
1 Mox Ruby (VMA) 8
1 Mox Sapphire (VMA) 9
1 Murktide Regent (MH2) 337 *F*
1 Opt (STA) 19
1 Otawara, Soaring City (NEO) 271
1 Path to Exile (PF20) 1 *F*
1 Phlage, Titan of Fire's Fury (MH3) 379
1 Plains (INV) 331 *F*
1 Plateau (VMA) 308
1 Polluted Delta (MH3) 224
1 Ponder (C21) 125
1 Preordain (CMR) 84
1 Prismatic Ending (MH2) 384
1 Prismatic Vista (H1R) 40 *E*
1 Pyrogoyf (M3C) 111
1 Pyrokinesis (ALL) 78
1 Ragavan, Nimble Pilferer (MH2) 138
1 Raugrin Triome (PIKO) 251p
1 Remand (RVR) 59
1 Sacred Foundry (GRN) 254
1 Satya, Aetherflux Genius (M3C) 3
1 Scalding Tarn (ZNE) 7
1 Seachrome Coast (ONE) 258
1 Seasoned Dungeoneer (CLB) 610
1 Serum Visions (5DN) 36
1 Shadowspear (THB) 236 *F*
1 Shivan Reef (DMU) 255
1 Sleight of Hand (9ED) 99
1 Snapcaster Mage (ISD) 78
1 Solitude (MH2) 307 *F*
1 Spirebluff Canal (KLD) 249
1 Steam Vents (RTR) 247
1 Stoneforge Mystic (SLD) 1253 *F*
1 Swords to Plowshares (ICE) 54
1 Tamiyo, Inquisitive Student // Tamiyo, Seasoned Scholar (MH3) 443
1 Teferi, Time Raveler (WAR) 221
1 Thought Scour (2X2) 351
1 Thundering Falls (MKM) 269
1 Tundra (VMA) 322
1 Umezawa's Jitte (BOK) 163
1 Unholy Heat (MH2) 145
1 Urza's Saga (MH2) 380
1 Volcanic Island (VMA) 324
1 Wasteland (SLD) 178
1 White Plume Adventurer (CLB) 558 *F*
1 Windswept Heath (KTK) 248
1 Wooded Foothills (KTK) 249

2390
output.pdf

File diff suppressed because it is too large Load Diff

View File

@ -101,18 +101,21 @@ pub fn main() !void {
constantHeight = std.mem.eql(u8, choice, "true");
}
const oracleFile = try cwd.openFile(oracleFileName, .{});
var jsonReader = json.reader(allocator, oracleFile.reader());
const parsedJson = try json.parseFromTokenSource([]Card, allocator, &jsonReader, .{ .ignore_unknown_fields = true });
var timer = try std.time.Timer.start();
const oracleFileSize = (try cwd.statFile(oracleFileName)).size;
const oracleFile = try cwd.readFileAlloc(allocator, oracleFileName, oracleFileSize);
const parsedJson = try json.parseFromSlice([]Card, allocator, oracleFile, .{ .ignore_unknown_fields = true });
var cardNames = std.BufSet.init(allocator);
const listText = try cwd.readFileAlloc(allocator, listFileName, 1024 * 100);
const listFileSize = (try cwd.statFile(listFileName)).size;
const listText = try cwd.readFileAlloc(allocator, listFileName, listFileSize);
var listLines = std.mem.splitAny(u8, listText, "\n");
while (listLines.next()) |line| {
if (line.len < 5) break;
const cardName = line[indexOf(u8, line, " ").? + 1 .. indexOf(u8, line, "(").? - 1];
try cardNames.insert(cardName);
}
print("{d}\n", .{timer.read() / 1_000_000_000});
var cards = std.StringArrayHashMap(TextCard).init(allocator);
for (parsedJson.value) |*cardObj| {
@ -164,6 +167,18 @@ fn card(
var fullUnformattedText = std.ArrayList(u8).init(allocator);
var oracleIterator = std.mem.splitAny(u8, cardObj.oracle_text, "()");
var oracleBuf = std.ArrayList(u8).init(allocator);
var oracleIdx: usize = 0;
while(oracleIterator.next()) |slice| : (oracleIdx += 1) {
if(oracleIdx % 2 != 0) continue;
try oracleBuf.appendSlice(slice);
}
var finalOracleText: [30 * 100]u8 = undefined;
_ = std.mem.replace(u8, oracleBuf.items, cardObj.name, "~", &finalOracleText);
print("{s}\n", .{finalOracleText});
if (cardObj.card_faces == null or cardObj.isFace) {
try fullUnformattedText.appendSlice(try std.mem.concat(allocator, u8, &[_][]const u8{
cardObj.name,
@ -172,7 +187,7 @@ fn card(
" (",
cardObj.type_line,
") >> ",
cardObj.oracle_text,
&finalOracleText,
if (cardObj.power) |_| " (" else "",
cardObj.power orelse "",
if (cardObj.power) |_| "/" else "",
@ -195,15 +210,20 @@ fn card(
}
var line = std.ArrayList(u8).init(allocator);
var wordIterator = std.mem.splitAny(u8, fullUnformattedText.items, "\n ");
//split on spaces, newlines and null
var wordIterator = std.mem.splitAny(u8, fullUnformattedText.items, &.{'\n',' ',170});
while (wordIterator.next()) |word| {
if (line.items.len + word.len + 1 >= cardWidth) {
try cardText.append(try line.toOwnedSlice());
line.clearAndFree();
}
if(word.len > 0) {
try line.appendSlice(word);
try line.append(' ');
print("{any}\n", .{word});
print("{s}\n", .{line.items});
assert(line.items.len < 30);
}
} else {
try cardText.append(try line.toOwnedSlice());
}

View File

@ -2,7 +2,7 @@ const std = @import("std");
const cwd = std.fs.cwd;
const json = std.json;
const print = std.debug.print;
const oracleFileName = "oracle-cards-20240701090158.json";
const oracleFileName = "oracle-data/oracle-cards-20240701090158.json";
const Card = struct {
name: []const u8 = "", //string
@ -21,34 +21,24 @@ const cardList = std.MultiArrayList(Card);
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const oracleFile = try cwd().openFile(oracleFileName, .{});
const fileReader = oracleFile.reader();
var bufferedReader = std.io.bufferedReader(fileReader);
const readerReader = bufferedReader.reader();
// var jsonReader = json.reader(allocator, oracleFile.reader());
// var fields = std.ArrayList(Field).init(allocator);
// var isVal = false;
// var cards = std.StringHashMap(*StringHashMap);
// var currentCard = std.ArrayList(std.json.Token).init(allocator);
var depth: u32 = 0;
var cardString = std.ArrayList(u8).init(allocator);
var idx: u32 = 0;
while (readerReader.readByte()) |char| {
if (char == '{') depth += 1;
if (depth != 0) try cardString.append(char);
if (char == '}') {
depth -= 1;
if (depth == 0) {
// print("{s}\n", .{cardString.items});
const parsedCard = try std.json.parseFromSlice(Card, allocator, cardString.items, .{ .ignore_unknown_fields = true });
print("{s}\n", .{parsedCard.value.name});
cardString.clearAndFree();
var cards = std.StringArrayHashMap.init(allocator);
var timer = try std.time.Timer.start();
const oracleFileSize = (try cwd().statFile(oracleFileName)).size;
const oracleFile = try cwd().readFileAlloc(allocator, oracleFileName, oracleFileSize);
var cardStrings = std.mem.splitSequence(u8, oracleFile, "{\"object\":\"card\",");
while (cardStrings.next()) |cardText| {
if(cardText.len > 5) {
const paddedText = try std.mem.concat(allocator, u8, &[_][]const u8{"{", cardText});
const trimmedText = std.mem.trimRight(u8, paddedText, ",\n]");
const card = try std.json.parseFromSlice(Card, allocator, trimmedText, .{.ignore_unknown_fields = true});
try cards.put(allocator, card.value.name, card.value);
}
}
idx += 1;
} else |e| {
return e;
for(cards.items(.name), 0..) |name, idx| {
if(std.mem.eql(u8, name, testCardName)) print("{any}\n", .{cards.get(idx)});
}
print("{d}\n", .{timer.read() / 1_000_000_000});
}

Binary file not shown.