const std = @import("std"); const json_utils = @import("../json_utils.zig"); const Store = @import("../store.zig"); const assert = std.debug.assert; const json = std.json; const ItemQuantity = @import("./item_quantity.zig"); pub fn BoundedSlotsArray(comptime slot_count: u32) type { const Slots = std.BoundedArray(ItemQuantity, slot_count); const CodeId = Store.CodeId; return struct { slots: Slots, pub fn init() @This() { return @This(){ .slots = Slots.init(0) catch unreachable }; } pub fn parse(api: *Store, slots_array: json.Array) !@This() { var slots = Slots.init(0) catch unreachable; for (slots_array.items) |slot_value| { const slot_obj = json_utils.asObject(slot_value) orelse return error.InvalidType; if (try ItemQuantity.parse(api, slot_obj)) |slot| { try slots.append(slot); } } return @This(){ .slots = slots }; } fn findSlotIndex(self: *const @This(), id: CodeId) ?usize { for (0.., self.slots.slice()) |i, *slot| { if (slot.id == id) { return i; } } return null; } fn findSlot(self: *@This(), id: CodeId) ?*ItemQuantity { if (self.findSlotIndex(id)) |index| { return &self.slots.buffer[index]; } return null; } pub fn remove(self: *@This(), id: CodeId, quantity: u64) void { const slot_index = self.findSlotIndex(id) orelse unreachable; const slot = self.slots.get(slot_index); assert(slot.quantity >= quantity); slot.quantity -= quantity; if (slot.quantity == 0) { self.slots.swapRemove(slot_index); } } pub fn add(self: *@This(), id: CodeId, quantity: u64) !void { if (quantity == 0) return; if (self.findSlot(id)) |slot| { slot.quantity += quantity; } else { try self.slots.append(ItemQuantity.init(id, quantity)); } } pub fn addSlice(self: *@This(), items: []const ItemQuantity) void { for (items) |item| { self.add(item.id, item.quantity); } } pub fn removeSlice(self: *@This(), items: []const ItemQuantity) void { for (items) |item| { self.remove(item.id, item.quantity); } } pub fn getQuantity(self: *const @This(), id: CodeId) u64 { if (self.findSlotIndex(id)) |index| { return self.slots.get(index).quantity; } return 0; } pub fn totalQuantity(self: *const @This()) u64 { var count: u64 = 0; for (self.slots.constSlice()) |slot| { count += slot.quantity; } return count; } pub fn slice(self: *@This()) []ItemQuantity { return self.slots.slice(); } }; }