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