mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
package transform
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"image/color"
|
|
"io"
|
|
"math/rand"
|
|
|
|
"github.com/prymitive/karma/internal/config"
|
|
"github.com/prymitive/karma/internal/models"
|
|
"github.com/prymitive/karma/internal/slices"
|
|
|
|
"github.com/prymitive/randomcolor"
|
|
"github.com/rs/zerolog/log"
|
|
plcolors "gopkg.in/go-playground/colors.v1"
|
|
)
|
|
|
|
func labelToSeed(key string, val string) int64 {
|
|
h := sha1.New()
|
|
_, _ = io.WriteString(h, key)
|
|
_, _ = io.WriteString(h, val)
|
|
|
|
var seed int64
|
|
for _, i := range h.Sum(nil) {
|
|
seed += int64(i)
|
|
}
|
|
return seed
|
|
}
|
|
|
|
func colorFromKeyVal(key, val string) color.Color {
|
|
r := rand.New(rand.NewSource(labelToSeed(key, val)))
|
|
return randomcolor.New(r, randomcolor.Random, randomcolor.LIGHT)
|
|
}
|
|
|
|
func rgbToBrightness(r, g, b uint8) int32 {
|
|
return ((int32(r) * 299) + (int32(g) * 587) + (int32(b) * 114)) / 1000
|
|
}
|
|
|
|
func parseCustomColor(colorStore models.LabelsColorMap, key, val, customColor string) {
|
|
color, err := plcolors.Parse(customColor)
|
|
if err != nil {
|
|
log.Warn().
|
|
Err(err).
|
|
Str("key", key).
|
|
Str("value", val).
|
|
Msg("Failed to parse custom color")
|
|
return
|
|
}
|
|
rgb := color.ToRGB()
|
|
bc := models.Color{
|
|
Red: rgb.R,
|
|
Green: rgb.G,
|
|
Blue: rgb.B,
|
|
Alpha: 255,
|
|
}
|
|
brightness := rgbToBrightness(bc.Red, bc.Green, bc.Blue)
|
|
if _, found := colorStore[key]; !found {
|
|
colorStore[key] = make(map[string]models.LabelColors)
|
|
}
|
|
colorStore[key][val] = models.LabelColors{
|
|
Brightness: brightness,
|
|
Background: bc.ToString(),
|
|
}
|
|
}
|
|
|
|
// ColorLabel update karmaColorMap object with a color object generated
|
|
// from label key and value passed here
|
|
// It's used to generate unique colors for configured labels
|
|
func ColorLabel(colorStore models.LabelsColorMap, key string, val string) {
|
|
// first handle custom colors
|
|
_, ok := config.Config.Labels.Color.Custom[key]
|
|
if ok {
|
|
for _, colorRule := range config.Config.Labels.Color.Custom[key] {
|
|
if colorRule.Value == val {
|
|
parseCustomColor(colorStore, key, val, colorRule.Color)
|
|
return
|
|
}
|
|
|
|
if colorRule.CompiledRegex != nil && colorRule.CompiledRegex.MatchString(val) {
|
|
parseCustomColor(colorStore, key, val, colorRule.Color)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// if no custom color is found then generate unique colors if needed
|
|
if slices.StringInSlice(config.Config.Labels.Color.Unique, key) {
|
|
if _, found := colorStore[key]; !found {
|
|
colorStore[key] = make(map[string]models.LabelColors)
|
|
}
|
|
if _, found := colorStore[key][val]; !found {
|
|
color := colorFromKeyVal(key, val)
|
|
red, green, blue, alpha := color.RGBA()
|
|
bc := models.Color{
|
|
Red: uint8(red >> 8),
|
|
Green: uint8(green >> 8),
|
|
Blue: uint8(blue >> 8),
|
|
Alpha: uint8(alpha >> 8),
|
|
}
|
|
// check if color is bright or dark and pick the right background
|
|
// uses https://www.w3.org/WAI/ER/WD-AERT/#color-contrast method
|
|
brightness := rgbToBrightness(bc.Red, bc.Green, bc.Blue)
|
|
colorStore[key][val] = models.LabelColors{
|
|
Brightness: brightness,
|
|
Background: bc.ToString(),
|
|
}
|
|
}
|
|
}
|
|
}
|