category.go (2360B)
1 package category 2 3 import ( 4 "fmt" 5 6 "code.dwrz.net/src/pkg/color" 7 "code.dwrz.net/src/pkg/dqs/portion" 8 ) 9 10 type Category struct { 11 Name string `json:"name"` 12 Portions []portion.Portion `json:"portions"` 13 HighQuality bool `json:"highQuality"` 14 } 15 16 func (c *Category) Add(q float64) error { 17 for i := range c.Portions { 18 p := &c.Portions[i] 19 // Done if there's less than a half-portion left. 20 if q < 0.5 { 21 break 22 } 23 24 switch p.Amount { 25 case portion.Full: 26 continue 27 case portion.Half: 28 p.Amount = portion.Full 29 q -= 0.5 30 case portion.None: 31 if q >= 1.0 { 32 p.Amount = portion.Full 33 q -= 1.0 34 } else if q >= 0.5 { 35 p.Amount = portion.Half 36 q -= 0.5 37 } 38 } 39 } 40 41 // Check if we were able to add all the portions. 42 if q > 0.5 { 43 return fmt.Errorf("too many portions of %s", c.Name) 44 } 45 46 return nil 47 } 48 49 func (c *Category) Score() (total float64) { 50 for _, p := range c.Portions { 51 total += p.Score() 52 } 53 54 return total 55 } 56 57 func (c *Category) FormatPrint() string { 58 var str = fmt.Sprintf("ā%-26sā", c.Name) 59 60 for _, p := range c.Portions { 61 var cellColor color.Color 62 63 switch { 64 case p.Points > 0 && p.Amount == portion.Full: 65 cellColor = color.BackgroundBrightGreen 66 case p.Points > 0 && p.Amount == portion.Half: 67 cellColor = color.BrightGreen 68 case p.Points == 0 && p.Amount == portion.Full: 69 cellColor = color.BackgroundBrightYellow 70 case p.Points == 0 && p.Amount == portion.Half: 71 cellColor = color.BrightYellow 72 case p.Points < 0 && p.Amount == portion.Full: 73 cellColor = color.BackgroundBrightRed 74 case p.Points < 0 && p.Amount == portion.Half: 75 cellColor = color.BrightRed 76 } 77 78 str += fmt.Sprintf("%s%+d%sā", cellColor, p.Points, color.Reset) 79 } 80 81 return str 82 } 83 84 func (c *Category) Remove(q float64) error { 85 for i := len(c.Portions) - 1; i >= 0; i-- { 86 p := &c.Portions[i] 87 // Done if there's less than a half-portion left. 88 if q < 0.5 { 89 break 90 } 91 92 switch p.Amount { 93 case portion.None: 94 continue 95 case portion.Half: 96 p.Amount = portion.None 97 q -= 0.5 98 case portion.Full: 99 if q >= 1.0 { 100 p.Amount = portion.None 101 q -= 1.0 102 } else if q >= 0.5 { 103 p.Amount = portion.Half 104 q -= 0.5 105 } 106 } 107 } 108 109 // Check if we were able to remove all the portions. 110 if q > 0.5 { 111 return fmt.Errorf("too many portions of %s", c.Name) 112 } 113 114 return nil 115 }