package bucket import "fmt" // Bucket to store volume type Bucket struct { // Capacity amount the bucket can store Capacity uint64 // Volume is the current volume of the bucket Volume uint64 } // Fill returns a copy Bucket filled func Fill(b Bucket) Bucket { return Bucket{ Volume: b.Capacity, Capacity: b.Capacity, } } // Empty returns a copy Bucket set to empty func Empty(b Bucket) Bucket { return Bucket{ Volume: 0, Capacity: b.Capacity, } } // Pour fills the target bucket to the top func Pour(src, target Bucket) (Bucket, Bucket) { s := Bucket{ Capacity: src.Capacity, Volume: src.Volume, } t := Bucket{ Capacity: target.Capacity, Volume: target.Volume, } availableVolume := t.Capacity - t.Volume if availableVolume > s.Volume { t.Volume += s.Volume s.Volume = 0 } else { s.Volume -= availableVolume t.Volume += availableVolume } return s, t } // Fill sets the volume to the capacity to fill bucket func (b *Bucket) Fill() { b.Volume = b.Capacity } // Empty sets the volume to 0 func (b *Bucket) Empty() { b.Volume = 0 } // IsEmpty is true no volume func (b *Bucket) IsEmpty() bool { return b.Volume == 0 } // IsFull is true if bucket is at capacity func (b *Bucket) IsFull() bool { return b.Volume == b.Capacity } // Pour fills the target bucket to the top func (b *Bucket) Pour(target *Bucket) { availableVolume := target.Capacity - target.Volume if availableVolume > b.Volume { target.Volume += b.Volume b.Volume = 0 } else { b.Volume -= availableVolume target.Volume += availableVolume } } // String gets string representation func (b *Bucket) String() string { return fmt.Sprintf("%dvol/%dcap", b.Volume, b.Capacity) }