const std = @import("std"); const json_utils = @import("json_utils.zig"); const Server = @import("./server.zig"); const ItemId = Server.ItemId; const assert = std.debug.assert; const json = std.json; const Slot = @import("./slot.zig"); pub fn BoundedSlotsArray(comptime slot_count: u32) type { const Slots = std.BoundedArray(Slot, slot_count); return struct { slots: Slots, pub fn init() @This() { return @This(){ .slots = Slots.init(0) catch unreachable }; } pub fn parse(api: *Server, 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 Slot.parse(api, slot_obj)) |slot| { try slots.append(slot); } } return @This(){ .slots = slots }; } fn findSlotIndex(self: *const @This(), id: ItemId) ?usize { for (0.., self.slots.slice()) |i, *slot| { if (slot.id == id) { return i; } } return null; } fn findSlot(self: *@This(), id: ItemId) ?*Slot { if (self.findSlotIndex(id)) |index| { return &self.slots.buffer[index]; } return null; } pub fn remove(self: *@This(), id: ItemId, 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: ItemId, quantity: u64) !void { if (quantity == 0) return; if (self.findSlot(id)) |slot| { slot.quantity += quantity; } else { try self.slots.append(Slot{ .id = id, .quantity = quantity }); } } pub fn addSlice(self: *@This(), items: []const Server.ItemIdQuantity) void { for (items) |item| { self.add(item.id, item.quantity); } } pub fn removeSlice(self: *@This(), items: []const Server.ItemIdQuantity) void { for (items) |item| { self.remove(item.id, item.quantity); } } pub fn getQuantity(self: *const @This(), id: ItemId) 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()) []Slot { return self.slots.slice(); } }; }