portion.go (960B)
1 package portion 2 3 import ( 4 "fmt" 5 "math" 6 "strconv" 7 ) 8 9 type Amount string 10 11 const ( 12 None Amount = "" 13 Full Amount = "full" 14 Half Amount = "half" 15 ) 16 17 func (a Amount) Claimed() bool { 18 switch a { 19 case Half, Full: 20 return true 21 default: 22 return false 23 } 24 } 25 26 type Portion struct { 27 Points int `json:"points"` 28 Amount Amount `json:"amount"` 29 } 30 31 func (p *Portion) Score() float64 { 32 switch p.Amount { 33 case Full: 34 return float64(p.Points) 35 case Half: 36 return float64(p.Points) / 2 37 case None: 38 fallthrough 39 default: 40 return float64(0) 41 } 42 } 43 44 func Parse(quantity string) (float64, error) { 45 q, err := strconv.ParseFloat(quantity, 64) 46 if err != nil { 47 return 0, fmt.Errorf( 48 "failed to parse quantity %s: %w", quantity, err, 49 ) 50 } 51 if q < 0 { 52 return 0, fmt.Errorf( 53 "negative portions (%s) are not allowed", quantity, 54 ) 55 } 56 if math.Mod(q, 0.5) != 0 { 57 return 0, fmt.Errorf( 58 "quantity %f is not a full or half portion", q, 59 ) 60 } 61 62 return q, nil 63 }