// Inventory System -- package inventory (finished). package inventory import ( "errors" "fmt" ) // Item is one collectable thing. Make one with NewItem. type Item struct { name string weight float64 value int } // NewItem returns an item. The name must not be empty, and the weight and the // value must not be below 0. func NewItem(name string, weight float64, value int) (*Item, error) { if name == "" { return nil, errors.New("an item needs a name") } if weight < 0 { return nil, fmt.Errorf("item %s: weight %.1f is below 0", name, weight) } if value < 0 { return nil, fmt.Errorf("item %s: value %d is below 0", name, value) } return &Item{name: name, weight: weight, value: value}, nil } // Name returns the item's name. func (it *Item) Name() string { return it.name } // Describe returns a one-line summary such as "sword (3.5kg, 50g)". func (it *Item) Describe() string { return fmt.Sprintf("%s (%.1fkg, %dg)", it.name, it.weight, it.value) } // Inventory is a container of items. Make one with New. type Inventory struct { items []*Item } // New returns an empty inventory. func New() *Inventory { return &Inventory{} } // Add puts an item in the inventory. func (inv *Inventory) Add(item *Item) { inv.items = append(inv.items, item) } // Remove takes out the first item with this name and returns it. It returns // nil if no item has this name. func (inv *Inventory) Remove(name string) *Item { for i, item := range inv.items { if item.name == name { inv.items = append(inv.items[:i], inv.items[i+1:]...) return item } } return nil } // TotalWeight returns the sum of the weights. func (inv *Inventory) TotalWeight() float64 { total := 0.0 for _, item := range inv.items { total = total + item.weight } return total } // TotalValue returns the sum of the values. func (inv *Inventory) TotalValue() int { total := 0 for _, item := range inv.items { total = total + item.value } return total } // Counts returns how many items there are with each name. func (inv *Inventory) Counts() map[string]int { counts := map[string]int{} for _, item := range inv.items { counts[item.name]++ } return counts } // List prints each item on its own line, then a line of totals. func (inv *Inventory) List() { fmt.Printf("Inventory (%d items):\n", len(inv.items)) for _, item := range inv.items { fmt.Println(" - " + item.Describe()) } fmt.Printf(" Totals: %.2fkg, %dg\n", inv.TotalWeight(), inv.TotalValue()) }