Skip to content

Commit

Permalink
feat: JSON morgue output
Browse files Browse the repository at this point in the history
  • Loading branch information
kiedtl committed Mar 2, 2023
1 parent 70d80a8 commit 6260337
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/buffer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,9 @@ pub fn StackBuffer(comptime T: type, comptime capacity: usize) type {
pub inline fn lastPtr(self: *Self) ?*T {
return if (self.len > 0) &self.data[self.len - 1] else null;
}

pub fn jsonStringify(val: @This(), opts: std.json.StringifyOptions, stream: anytype) !void {
try std.json.stringify(val.constSlice(), opts, stream);
}
};
}
108 changes: 95 additions & 13 deletions src/scores.zig
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,26 @@ pub const StatValue = struct {
pub const SingleUsize = struct {
total: usize = 0,
each: [LEVELS]usize = [1]usize{0} ** LEVELS,

pub fn jsonStringify(val: SingleUsize, opts: std.json.StringifyOptions, stream: anytype) !void {
const JsonValue = struct { floor_type: []const u8, floor_name: []const u8, value: usize };
var object: struct { total: usize, values: StackBuffer(JsonValue, LEVELS) } = .{
.total = val.total,
.values = StackBuffer(JsonValue, LEVELS).init(null),
};

var c: usize = state.levelinfo.len - 1;
while (c > 0) : (c -= 1) if (_isLevelSignificant(c)) {
const v = JsonValue{
.floor_type = state.levelinfo[c].id,
.floor_name = state.levelinfo[c].name,
.value = val.each[c],
};
object.values.append(v) catch err.wat();
};

try std.json.stringify(object, opts, stream);
}
};
};

Expand Down Expand Up @@ -372,7 +392,7 @@ fn _isLevelSignificant(level: usize) bool {
return data[@enumToInt(@as(Stat, .TurnsSpent))].SingleUsize.each[level] > 0;
}

fn formatMorgue(info: Info, alloc: mem.Allocator) !std.ArrayList(u8) {
fn exportTextMorgue(info: Info, alloc: mem.Allocator) !std.ArrayList(u8) {
var buf = std.ArrayList(u8).init(alloc);
var w = buf.writer();

Expand Down Expand Up @@ -580,14 +600,54 @@ fn formatMorgue(info: Info, alloc: mem.Allocator) !std.ArrayList(u8) {
return buf;
}

pub fn createMorgue() Info {
const info = Info.collect();
fn exportJsonMorgue(info: Info) !std.ArrayList(u8) {
var buf = std.ArrayList(u8).init(state.GPA.allocator());
var w = buf.writer();

const morgue = formatMorgue(info, state.GPA.allocator()) catch err.wat();
defer morgue.deinit();
try w.writeAll("{");

try w.writeAll("\"info\":");
try std.json.stringify(info, .{}, w);

try w.writeAll(",\"stats\":{");
for (&CHUNKS) |chunk, chunk_i| switch (chunk) {
.Header => {},
.Stat => |stat| {
const entry = &data[@enumToInt(stat.s)];
try w.print("\"{s}\": {{", .{stat.n});
try w.print("\"type\": \"{s}\",", .{@tagName(stat.s.stattype())});
switch (stat.s.stattype()) {
.SingleUsize => {
try w.writeAll("\"value\":");
try std.json.stringify(entry.SingleUsize, .{}, w);
},
.BatchUsize => {
try w.writeAll("\"values\": [");
for (entry.BatchUsize.singles.slice()) |batch_entry, i| {
try w.print("{{ \"name\": \"{s}\", \"value\":", .{batch_entry.id.constSlice()});
try std.json.stringify(batch_entry.val, .{}, w);
try w.writeAll("}");
if (i != entry.BatchUsize.singles.slice().len - 1)
try w.writeAll(",");
}
try w.writeAll("]");
},
}
try w.writeAll("}");

const filename = std.fmt.allocPrintZ(state.GPA.allocator(), "morgue-{s}-{}-{}-{:0>2}-{:0>2}-{}:{}.txt", .{ info.username.constSlice(), rng.seed, info.end_datetime.Y, info.end_datetime.M, info.end_datetime.D, info.end_datetime.h, info.end_datetime.m }) catch err.oom();
defer state.GPA.allocator().free(filename);
if (chunk_i != CHUNKS.len - 1)
try w.writeAll(",");
},
};
try w.writeByte('}');

try w.writeByte('}');

return buf;
}

pub fn createMorgue() Info {
const info = Info.collect();

std.os.mkdir("morgue", 0o776) catch |e| switch (e) {
error.PathAlreadyExists => {},
Expand All @@ -598,12 +658,34 @@ pub fn createMorgue() Info {
},
};

(std.fs.cwd().openDir("morgue", .{}) catch err.wat()).writeFile(filename, morgue.items[0..]) catch |e| {
std.log.err("Could not write to morgue file '{s}': {}", .{ filename, e });
std.log.err("Refusing to write morgue entries.", .{});
return info;
};
std.log.info("Morgue file written to {s}.", .{filename});
{
const morgue = exportJsonMorgue(info) catch err.wat();
defer morgue.deinit();

const filename = std.fmt.allocPrintZ(state.GPA.allocator(), "morgue-{s}-{}-{}-{:0>2}-{:0>2}-{}:{}.json", .{ info.username.constSlice(), rng.seed, info.end_datetime.Y, info.end_datetime.M, info.end_datetime.D, info.end_datetime.h, info.end_datetime.m }) catch err.oom();
defer state.GPA.allocator().free(filename);

(std.fs.cwd().openDir("morgue", .{}) catch err.wat()).writeFile(filename, morgue.items[0..]) catch |e| {
std.log.err("Could not write to morgue file '{s}': {}", .{ filename, e });
std.log.err("Refusing to write morgue entries.", .{});
return info;
};
std.log.info("Morgue file written to {s}.", .{filename});
}
{
const morgue = exportTextMorgue(info, state.GPA.allocator()) catch err.wat();
defer morgue.deinit();

const filename = std.fmt.allocPrintZ(state.GPA.allocator(), "morgue-{s}-{}-{}-{:0>2}-{:0>2}-{}:{}.txt", .{ info.username.constSlice(), rng.seed, info.end_datetime.Y, info.end_datetime.M, info.end_datetime.D, info.end_datetime.h, info.end_datetime.m }) catch err.oom();
defer state.GPA.allocator().free(filename);

(std.fs.cwd().openDir("morgue", .{}) catch err.wat()).writeFile(filename, morgue.items[0..]) catch |e| {
std.log.err("Could not write to morgue file '{s}': {}", .{ filename, e });
std.log.err("Refusing to write morgue entries.", .{});
return info;
};
std.log.info("Morgue file written to {s}.", .{filename});
}

return info;
}
30 changes: 28 additions & 2 deletions src/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,10 @@ pub const Status = enum {
};
}

pub fn jsonStringify(val: Status, opts: std.json.StringifyOptions, stream: anytype) !void {
try std.json.stringify(val.string(state.player), opts, stream);
}

// Tick functions {{{

pub fn tickDetectHeat(mob: *Mob) void {
Expand Down Expand Up @@ -1621,6 +1625,30 @@ pub const StatusDataInfo = struct {
Equ,
Tmp: usize,
Ctx: ?*const surfaces.Terrain,

pub fn jsonStringify(val: Duration, opts: std.json.StringifyOptions, stream: anytype) !void {
try stream.writeByte('{');

try stream.writeAll("\"duration_type\":");
try stream.writeByte('"');
try stream.writeAll(@tagName(val));
try stream.writeByte('"');
try stream.writeByte(',');

// val.Ctx should never be null, in theory, but it is an optional
// for some reason... Just putting a check here to be safe...
//
if (val == .Tmp or (val == .Ctx and val.Ctx != null)) {
try stream.writeAll("\"duration_arg\":");
if (val == .Tmp) {
try std.json.stringify(val.Tmp, opts, stream);
} else {
try std.json.stringify(val.Ctx.?.id, opts, stream);
}
}

try stream.writeByte('}');
}
};
};

Expand Down Expand Up @@ -2198,8 +2226,6 @@ pub const Mob = struct { // {{{

// Set the dummy .Ctx durations' values.
//
// (See surfaces.Terrain.)
//
if (meta.activeTag(effect.duration) == .Ctx) {
adj_effect.duration = .{ .Ctx = terrain };
}
Expand Down

0 comments on commit 6260337

Please sign in to comment.