package billcost import "fmt" // CalculateShipCost computes the cost of shipping a parcel weighing // weightG grams using the given province's bands. The bands must // already be filtered to a single partition (the function does not // inspect Band.Partition); callers that hold a multi-partition slice // should group by Partition first. // // Algorithm: // 1. Find the band b where b.LimitBottom < weightG <= b.LimitTop. // 2. cost := b.BaseAmount (first-weight flat charge). // 3. If weightG > b.BaseWeight and b.IncrementWeight > 0: // extra := weightG - b.BaseWeight // units := ceil(extra / b.IncrementWeight) // cost += units * b.IncrementPrice // // Returns an "uncovered" error when no band covers weightG, which // the reflector treats as a coverage / gap rule violation. // // CalculateShipCost 给出按 bands 算的运费. bands 必须已过滤到单一 // 分区 (函数不检查 Band.Partition); 持多分区切片的调用方先按 Partition // group. // // 算法: // 1. 找命中段 b: b.LimitBottom < weightG <= b.LimitTop. // 2. cost := b.BaseAmount (首重一口价). // 3. weightG > b.BaseWeight 且 b.IncrementWeight > 0 时: // extra := weightG - b.BaseWeight // units := ceil(extra / b.IncrementWeight) // cost += units * b.IncrementPrice // // 无段命中返 "uncovered" 错, 反射器记 coverage / gap 类违规. func CalculateShipCost(bands []Band, weightG int) (float64, error) { for _, b := range bands { if weightG > b.LimitBottom && weightG <= b.LimitTop { cost := b.BaseAmount if weightG > b.BaseWeight && b.IncrementWeight > 0 { extra := weightG - b.BaseWeight units := ceilDiv(extra, b.IncrementWeight) cost += float64(units) * b.IncrementPrice } return cost, nil } } return 0, fmt.Errorf("billcost: weight %dg uncovered by bands", weightG) } // ceilDiv returns ceil(a/b) for non-negative a and positive b. // // ceilDiv 返 ceil(a/b), 要求 a 非负 b 正. func ceilDiv(a, b int) int { if b <= 0 { return 0 } if a <= 0 { return 0 } return (a + b - 1) / b }