func (b *TargetBuilder) TargetSaturation(value float64) *TargetBuilder {
	b.result.targetSaturation = clampFloat64(value, 0, 1)
	return b
}
Set the target/ideal saturation value for this target.
package vibrant
import (
	"fmt"
	"math"
)
const (
	MinNormalLightness    = 0.3
	TargetNormalLightness = 0.5
	MaxNormalLightness    = 0.7
	MinLightLightness    = 0.55
	TargetLightLightness = 0.74
	TargetDarkLightness = 0.26
	MaxDarkLightness    = 0.45
	TargetVibrantSaturation = 1
	MinVibrantSaturation    = 0.35
	TargetMutedSaturation = 0.3
	MaxMutedSaturation    = 0.4
	DefaultSaturationWeight = 0.375
	DefaultLightnessWeight  = 0.575
	DefaultPopulationWeight = 0.05
)
var (
	LightVibrant *Target
	Vibrant *Target
	DarkVibrant *Target
	LightMuted *Target
	Muted *Target
	DarkMuted *Target
)
var (
	DefaultScorerFactory ScorerFactory
)
func init() {
	DefaultScorerFactory = ScorerFactory(func(target Target, swatches []*Swatch) Scorer {
		maxPopulation := uint32(0)
		for _, swatch := range swatches {
			if swatch.Population() > maxPopulation {
				maxPopulation = swatch.Population()
			}
		}
		return NewDefaultScorer(target, maxPopulation)
	})
	LightVibrant = NewTargetBuilder().
		MinimumLightness(MinLightLightness).
		TargetLightness(TargetLightLightness).
		MinimumSaturation(MinVibrantSaturation).
		TargetSaturation(TargetVibrantSaturation).
		Build()
	Vibrant = NewTargetBuilder().
		MinimumLightness(MinNormalLightness).
		TargetLightness(TargetNormalLightness).
		MaximumLightness(MaxNormalLightness).
		MinimumSaturation(MinVibrantSaturation).
		TargetSaturation(TargetVibrantSaturation).
		Build()
	DarkVibrant = NewTargetBuilder().
		TargetLightness(TargetDarkLightness).
		MaximumLightness(MaxDarkLightness).
		MinimumSaturation(MinVibrantSaturation).
		TargetSaturation(TargetVibrantSaturation).
		Build()
	LightMuted = NewTargetBuilder().
		MinimumLightness(MinLightLightness).
		TargetLightness(TargetLightLightness).
		TargetSaturation(TargetMutedSaturation).
		MaximumSaturation(MaxMutedSaturation).
		Build()
	Muted = NewTargetBuilder().
		MinimumLightness(MinNormalLightness).
		TargetLightness(TargetNormalLightness).
		MaximumLightness(MaxNormalLightness).
		TargetSaturation(TargetMutedSaturation).
		MaximumSaturation(MaxMutedSaturation).
		Build()
	DarkMuted = NewTargetBuilder().
		TargetLightness(TargetDarkLightness).
		MaximumLightness(MaxDarkLightness).
		TargetSaturation(TargetMutedSaturation).
		MaximumSaturation(MaxMutedSaturation).
		Build()
}
type Scorer interface {
	Score(*Swatch) float64
}
type DefaultScorer struct {
	target        Target
	maxPopulation uint32
}
func NewDefaultScorer(target Target, maxPopulation uint32) Scorer {
	return &DefaultScorer{
		target:        target,
		maxPopulation: maxPopulation,
	}
}
func (s DefaultScorer) Score(swatch *Swatch) float64 {
	hsl := swatch.HSL()
	if hsl.S < s.target.MinimumSaturation() || hsl.S > s.target.MaximumSaturation() {
		return 0
	}
	if hsl.L < s.target.MinimumLightness() || hsl.L > s.target.MaximumLightness() {
		return 0
	}
	saturationScore := DefaultSaturationWeight * (1.0 - math.Abs(hsl.S-s.target.TargetSaturation()))
	lightnessScore := DefaultLightnessWeight * math.Pow(1.0-math.Abs(hsl.L-s.target.TargetLightness()), 2)
	populationScore := DefaultPopulationWeight * (float64(swatch.Population()) / float64(s.maxPopulation))
	return saturationScore + lightnessScore + populationScore
}
type ScorerFactory func(Target, []*Swatch) Scorer
type Target struct {
	minimumSaturation float64
	targetSaturation  float64
	maximumSaturation float64
	minimumLightness float64
	targetLightness  float64
	maximumLightness float64
	isExclusive bool
	scorerFactory ScorerFactory
}
func newTarget() *Target {
	return &Target{
		minimumSaturation: 0,
		targetSaturation:  0.5,
		maximumSaturation: 1,
		minimumLightness:  0,
		targetLightness:   0.5,
		maximumLightness:  1,
		isExclusive:       true,
		scorerFactory:     DefaultScorerFactory,
	}
}
func newTargetFromTarget(other *Target) *Target {
	return &Target{
		minimumSaturation: other.minimumSaturation,
		targetSaturation:  other.targetSaturation,
		maximumSaturation: other.maximumSaturation,
		minimumLightness:  other.minimumLightness,
		targetLightness:   other.targetLightness,
		maximumLightness:  other.maximumLightness,
		isExclusive:       other.isExclusive,
		scorerFactory:     other.scorerFactory,
	}
}
func (t Target) String() string {
	return fmt.Sprintf("Saturation (%0.2f, %0.2f, %0.2f) Lightness (%0.2f, %0.2f, %0.2f) Exclusive (%v)", t.minimumSaturation, t.targetSaturation, t.maximumLightness, t.minimumLightness, t.targetLightness, t.maximumLightness, t.isExclusive)
}
func (t Target) MinimumSaturation() float64 {
	return t.minimumSaturation
}
func (t Target) TargetSaturation() float64 {
	return t.targetSaturation
}
func (t Target) MaximumSaturation() float64 {
	return t.maximumSaturation
}
func (t Target) MinimumLightness() float64 {
	return t.minimumLightness
}
func (t Target) TargetLightness() float64 {
	return t.targetLightness
}
func (t Target) MaximumLightness() float64 {
	return t.maximumLightness
}
func (t Target) IsExclusive() bool {
	return t.isExclusive
}
func (t Target) Scorer(swatches []*Swatch) Scorer {
	return t.scorerFactory(t, swatches)
}
type TargetBuilder struct {
	result *Target
}
func NewTargetBuilder() *TargetBuilder {
	return &TargetBuilder{
		result: newTarget(),
	}
}
func NewTargetBuilderFromTarget(target *Target) *TargetBuilder {
	return &TargetBuilder{
		result: newTargetFromTarget(target),
	}
}
func (b *TargetBuilder) MinimumSaturation(value float64) *TargetBuilder {
	b.result.minimumSaturation = clampFloat64(value, 0, 1)
	return b
}