package pill import ( // Used for embedding pill. _ "embed" "fmt" "io" "math" "text/template" ) var ( //go:embed pill.svg pill string tmpl = template.New("svgTemplate") ) const ( modifier = 0.2 max = 190 blue = 55 ) // Pill is used to execute the pill.svg template. // Width is dependent on whether the percentage is 2 digits or 3 digits. type Pill struct { Percentage string Colour string Width string } // NewPill creates creates a Pill, automatically calculating the colour, width, and formatting the percentage. // Note: %.0f gives us a float with 0 decimals and 0 padding for 2 numbers less than 10. func NewPill(percentDecimal float64) Pill { square := math.Pow(percentDecimal, 2) red := modifier + clamp(2-2*square, 0, 1)*(1-modifier) green := modifier + clamp(2*square, 0, 1)*(1-modifier) percentage := fmt.Sprintf("%.0f", percentDecimal*100) colour := fmt.Sprintf("rgb(%.0f, %.0f, %d)", red*max, green*max, blue) width := "250" if len(percentage) == 1 { width = "170" } if len(percentage) == 3 { width = "310" } return Pill{ Percentage: percentage + "%", Colour: colour, Width: width, } } func UnknownPill() Pill { return Pill{ Percentage: "N/A", Colour: "#353535", Width: "220", } } var pillTemplate = template.Must(tmpl.Parse(pill)) // Execute runs the pill template with the data and writes the result to the writer given. func (p Pill) Execute(w io.Writer) error { return tmpl.Execute(w, p) } func clamp(n, min, max float64) float64 { switch { case n > max: return max case n < min: return min default: return n } }