new way of doing things! it's slower :((

This commit is contained in:
Lumen Keyes 2024-07-06 00:18:29 -06:00
parent be11ed54dd
commit b9945e8097
2 changed files with 206 additions and 117 deletions

View File

@ -11,28 +11,19 @@ const expect = std.testing.expect;
const assert = std.debug.assert;
const Card = struct {
name: []const u8 = "",//string
mana_cost: []const u8 = "",//string
cmc: f32 = 0,//technically a float? but I think we can always cast safely cast. EDIT: NOPE
type_line: []const u8 = "",//string
oracle_text: []const u8 = "",//string
power: []const u8 = "",//coerced to string
toughness: []const u8 = "",//coerced to string
card_faces: ?[]Card = null,//array of cards
name: []const u8 = "", //string
mana_cost: []const u8 = "", //string
cmc: f32 = 0, //technically a float? but I think we can always cast safely cast. EDIT: NOPE
type_line: []const u8 = "", //string
oracle_text: []const u8 = "", //string
power: []const u8 = "", //coerced to string
toughness: []const u8 = "", //coerced to string
card_faces: ?[]Card = null, //array of cards
};
const TextCard = struct {
lines: [][]const u8 = undefined
};
const TextCard = struct { lines: [][]const u8 = undefined };
const PandocOptions = &[_][]const u8{
"pandoc",
"out.md",
"-o", "out.pdf",
"--pdf-engine", "xelatex",
"-V", "mainfont:Liberation Mono",
"-V", "geometry:margin=0cm"
};
const PandocOptions = &[_][]const u8{ "pandoc", "out.md", "-o", "out.pdf", "--pdf-engine", "xelatex", "-V", "mainfont:Liberation Mono", "-V", "geometry:margin=0cm" };
//dimension constants and defaults
const cardWidth = 30;
@ -41,7 +32,6 @@ const minCardHeight = 5;
const pageHeight = 66;
var heightMayVary = false;
const formatString = "{s: <" ++ std.fmt.digits2(cardWidth) ++ "}";
const lineFormatter = "|" ++ formatString;
const spacer: []const u8 = "|" ++ (" " ** cardWidth);
@ -62,7 +52,9 @@ pub fn main() !void {
//TODO: properly handle program arguments
_ = args.next(); //handle program name (args[0])
const listFileName: []const u8 = args.next() orelse {return error.ExpectedArgument;};
const listFileName: []const u8 = args.next() orelse {
return error.ExpectedArgument;
};
heightMayVary = stringToBool(args.next());
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
@ -70,66 +62,114 @@ pub fn main() !void {
const allocator = arena.allocator();
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 allCards = std.StringHashMap(Card).init(allocator);
for(parsedJson.value) |cardObj| {
try allCards.put(cardObj.name, cardObj);
}
parsedJson.deinit();
var line = std.ArrayList(u8).init(allocator);
// var jsonReader = json.reader(allocator, oracleFile.reader());
// const parsedJson = try json.parseFromTokenSource([]Card, allocator, &jsonReader, .{.ignore_unknown_fields = true});
var cardNames = std.ArrayList([]const u8).init(allocator);
const listReader = (try cwd.openFile(listFileName, .{})).reader();
var allPrinted = std.ArrayList(u8).init(allocator);
var cards = std.ArrayList(TextCard).init(allocator);
// var pages = std.ArrayList(page).init(allocator);
var line = std.ArrayList(u8).init(allocator);
while (listReader.streamUntilDelimiter(line.writer(), '\n', null)) {
defer line.clearRetainingCapacity();
const cardName = line.items[indexOf(u8, line.items, " ").? + 1..indexOf(u8, line.items, "(").? - 1];
assert(cardName.len > 0);
const cardText = try card(allCards.get(cardName).?);
try cards.append(cardText);
} else |err| switch(err) {
const cardName = line.items[indexOf(u8, line.items, " ").? + 1 .. indexOf(u8, line.items, "(").? - 1];
try cardNames.append(try allocator.dupe(u8, cardName));
} else |err| switch (err) {
error.EndOfStream => {},
else => return err,
}
for(cards.items) |cardText| {
std.debug.print("{any}\n", .{cardText});
var depth: u32 = 0;
var cardString = std.ArrayList(u8).init(allocator);
var cards = std.StringHashMap(Card).init(allocator);
while (oracleFile.reader().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 });
var lookupTimer = try std.time.Timer.start();
for (cardNames.items, 0..) |cardName, i| {
if (std.mem.eql(u8, parsedCard.value.name, cardName)) {
// print("{s}\n", .{parsedCard.value.name});
try cards.putNoClobber(try allocator.dupe(u8, parsedCard.value.name), (try allocator.dupe(Card, &[_]Card{parsedCard.value}))[0]);
_ = cardNames.orderedRemove(i);
}
}
cardString.clearAndFree();
print("took {d:.10}\n", .{lookupTimer.read() / (1000 * 1000 * 1000)});
}
}
} else |e| {
switch (e) {
error.EndOfStream => {},
else => {
return e;
},
}
}
var cardIterator = cards.valueIterator();
while (cardIterator.next()) |cardObj| {
print("{any}\n", .{cardObj});
}
// var allCards = std.StringHashMap(Card).init(allocator);
// for(parsedJson.value) |cardObj| {
// try allCards.put(cardObj.name, cardObj);
// }
// parsedJson.deinit();
//
// var allPrinted = std.ArrayList(u8).init(allocator);
// var cards = std.ArrayList(TextCard).init(allocator);
// // var pages = std.ArrayList(page).init(allocator);
// while (listReader.streamUntilDelimiter(line.writer(), '\n', null)) {
// defer line.clearRetainingCapacity();
// const cardName = line.items[indexOf(u8, line.items, " ").? + 1..indexOf(u8, line.items, "(").? - 1];
// assert(cardName.len > 0);
// const cardText = try card(allCards.get(cardName).?);
// try cards.append(cardText);
// } else |err| switch(err) {
// error.EndOfStream => {},
// else => return err,
// }
//
// for(cards.items) |cardText| {
// std.debug.print("{any}\n", .{cardText});
// }
//sort the cards
std.mem.sort(TextCard, cards.items, {}, compareTwo);
// std.mem.sort(TextCard, cards.items, {}, compareTwo);
//TODO (fixme): absolutely GARBAGE hack to get pandoc to preserve whitespace
try allPrinted.appendSlice(markdownFormatString);
// try allPrinted.appendSlice(markdownFormatString);
var rowToPrint = std.ArrayList(TextCard).init(allocator);
for(cards.items) |cardObj| {
try rowToPrint.append(cardObj);
std.debug.print("{any}\n", .{cardObj});
if(rowToPrint.items.len >= 3) {
try cardRow.print(allocator, rowToPrint.items, &allPrinted);
rowToPrint.clearAndFree();
}
} else {
try cardRow.print(allocator, rowToPrint.items, &allPrinted);
try allPrinted.appendSlice(markdownFormatString);
std.debug.print("{s}", .{allPrinted.items});
try cwd.writeFile(.{.sub_path = "out.md", .data = allPrinted.items});
rowToPrint.clearAndFree();
var pandocProcess = std.process.Child.init(PandocOptions, allocator);
_ = try pandocProcess.spawnAndWait();
}
// var rowToPrint = std.ArrayList(TextCard).init(allocator);
// for(cards.items) |cardObj| {
// try rowToPrint.append(cardObj);
// std.debug.print("{any}\n", .{cardObj});
// if(rowToPrint.items.len >= 3) {
// try cardRow.print(allocator, rowToPrint.items, &allPrinted);
// rowToPrint.clearAndFree();
// }
// // } else {
// try cardRow.print(allocator, rowToPrint.items, &allPrinted);
// try allPrinted.appendSlice(markdownFormatString);
// std.debug.print("{s}", .{allPrinted.items});
// try cwd.writeFile(.{.sub_path = "out.md", .data = allPrinted.items});
// rowToPrint.clearAndFree();
// var pandocProcess = std.process.Child.init(PandocOptions, allocator);
// _ = try pandocProcess.spawnAndWait();
// }
}
fn compareTwo(_: void, a: TextCard, b: TextCard) bool {
return a.lines.len < b.lines.len;
}
fn card(cardObj: Card,) !TextCard {
fn card(
cardObj: Card,
) !TextCard {
var buffer: [cardHeight * 1024]u8 = undefined;
var cardTextAllocator = std.heap.FixedBufferAllocator.init(&buffer);
defer cardTextAllocator.reset();
@ -139,36 +179,38 @@ fn card(cardObj: Card,) !TextCard {
var fullUnformattedText = std.ArrayList(u8).init(cta);
try fullUnformattedText.appendSlice(cardObj.name);
try fullUnformattedText.appendSlice(try std.mem.concat(cta, u8, &[_][]const u8{
if(cardObj.mana_cost.len > 0) " " else "",
if (cardObj.mana_cost.len > 0) " " else "",
cardObj.mana_cost,
" (",
cardObj.type_line,
") >> ",
cardObj.oracle_text,
if(cardObj.power.len > 0) " >> " else "",
if (cardObj.power.len > 0) " >> " else "",
cardObj.power,
if(cardObj.power.len > 0) "/" else "",
if (cardObj.power.len > 0) "/" else "",
cardObj.toughness,
}));
if(cardObj.card_faces) |faces| {
for(faces, 0..) |face, idx| {
if (cardObj.card_faces) |faces| {
for (faces, 0..) |face, idx| {
try fullUnformattedText.appendSlice(face.oracle_text);
if(face.power.len > 0) try fullUnformattedText.appendSlice(" ");
if (face.power.len > 0) try fullUnformattedText.appendSlice(" ");
try fullUnformattedText.appendSlice(face.power);
if(face.power.len > 0) try fullUnformattedText.appendSlice("/");
if (face.power.len > 0) try fullUnformattedText.appendSlice("/");
try fullUnformattedText.appendSlice(face.toughness);
if(idx == 0) try fullUnformattedText.appendSlice(" // ");
if (idx == 0) try fullUnformattedText.appendSlice(" // ");
}
}
var line = std.ArrayList(u8).init(cta);
var word = std.ArrayList(u8).init(cta);
for(fullUnformattedText.items) |char| {
try switch(char) {
for (fullUnformattedText.items) |char| {
try switch (char) {
'\n', ' ' => addWord(&word, &line, &cardText),
else => if(std.ascii.isASCII(char)) {try word.append(char);}
else => if (std.ascii.isASCII(char)) {
try word.append(char);
},
};
} else {
try addWord(&word, &line, &cardText);
@ -177,12 +219,12 @@ fn card(cardObj: Card,) !TextCard {
try cardText.append(lineToBeAdded);
line.clearAndFree();
}
while(wrongCardHeight(cardText.items.len)) {
while (wrongCardHeight(cardText.items.len)) {
try cardText.append(" " ** (cardWidth - 2));
}
try cardText.append(" " ** (cardWidth - 2));
// return cardText.items;
return TextCard{.lines = try cardText.toOwnedSlice()};
return TextCard{ .lines = try cardText.toOwnedSlice() };
}
fn wrongCardHeight(length: usize) bool {
@ -190,7 +232,7 @@ fn wrongCardHeight(length: usize) bool {
}
fn addWord(word: *std.ArrayList(u8), line: *std.ArrayList(u8), cardText: *std.ArrayList([]const u8)) !void {
if(line.items.len + word.items.len >= (cardWidth)) {
if (line.items.len + word.items.len >= (cardWidth)) {
const lineToBeAdded = std.mem.trimRight(u8, try line.toOwnedSlice(), " ");
assert(lineToBeAdded.len < 30);
try cardText.append(lineToBeAdded);
@ -201,7 +243,7 @@ fn addWord(word: *std.ArrayList(u8), line: *std.ArrayList(u8), cardText: *std.Ar
word.clearAndFree();
}
const linesList = std.MultiArrayList(cardRow);
const cardRow = struct{
const cardRow = struct {
first: []const u8 = spacer,
second: []const u8 = spacer,
third: []const u8 = spacer,
@ -213,24 +255,24 @@ const cardRow = struct{
var lines = linesList{};
defer lines.deinit(gpa.allocator());
for(cards, 0..) |cardObj, cardNo| {
for (cards, 0..) |cardObj, cardNo| {
//const cardText = try card(cardObj);
const cardText = cardObj.lines;
for(cardText, 0..) |line, idx| {
for (cardText, 0..) |line, idx| {
//this step is probably unnecessary
const strippedLine = std.mem.trimRight(u8, line, " ");
const paddedLine = try std.fmt.allocPrint(gpa.allocator(), lineFormatter, .{strippedLine});
const theoreticalLength = (paddedLine.len * 3) + 1;
assert(paddedLine.len == spacer.len);
assert(theoreticalLength == pageWidth);
const placeholder = if(idx < lines.items(.first).len) lines.get(idx) else cardRow{};
const new: cardRow = switch(cardNo) {
0 => .{.first = paddedLine},
1 => .{.first = placeholder.first, .second = paddedLine},
2 => .{.first = placeholder.first, .second = placeholder.second, .third = paddedLine},
else => unreachable
const placeholder = if (idx < lines.items(.first).len) lines.get(idx) else cardRow{};
const new: cardRow = switch (cardNo) {
0 => .{ .first = paddedLine },
1 => .{ .first = placeholder.first, .second = paddedLine },
2 => .{ .first = placeholder.first, .second = placeholder.second, .third = paddedLine },
else => unreachable,
};
if(idx < lines.items(.first).len) {
if (idx < lines.items(.first).len) {
lines.set(idx, new);
} else {
try lines.append(gpa.allocator(), new);
@ -238,19 +280,14 @@ const cardRow = struct{
}
}
const rowHeight = lines.items(.first).len;
while(remainingPage(allPrinted.items.len) <= rowHeight) {
while (remainingPage(allPrinted.items.len) <= rowHeight) {
try allPrinted.appendSlice(fullWidthSpacer);
}
for(lines.items(.first), 0..) |_,idx| {
for (lines.items(.first), 0..) |_, idx| {
const line = lines.get(idx);
const printedWidth = line.first.len + line.second.len + line.third.len + line.last.len;
assert(printedWidth == pageWidth);
const fullLine = try std.mem.concat(gpa.allocator(), u8, &[_][]const u8{
line.first,
line.second,
line.third,
line.last
});
const fullLine = try std.mem.concat(gpa.allocator(), u8, &[_][]const u8{ line.first, line.second, line.third, line.last });
try allPrinted.appendSlice(fullLine);
}
}

52
src/selectiveParse.zig Normal file
View File

@ -0,0 +1,52 @@
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 Card = struct {
name: []const u8 = "", //string
mana_cost: []const u8 = "", //string
cmc: f32 = 0, //technically a float? but I think we can always cast safely cast. EDIT: NOPE
type_line: []const u8 = "", //string
oracle_text: []const u8 = "", //string
power: []const u8 = "", //coerced to string
toughness: []const u8 = "", //coerced to string
card_faces: ?[]Card = null, //array of cards
};
const testCardName = "Raffine, Scheming Seer";
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 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 (fileReader.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();
}
}
idx += 1;
} else |e| {
return e;
}
}