src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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 }