sampler-fork/component/gauge/gauge.go

128 lines
2.8 KiB
Go
Raw Normal View History

2019-02-26 04:36:23 +00:00
package gauge
import (
"fmt"
2019-03-14 03:01:44 +00:00
ui "github.com/gizak/termui/v3"
2019-03-13 03:19:19 +00:00
"github.com/sqshq/sampler/component"
2019-04-07 18:26:20 +00:00
"github.com/sqshq/sampler/component/util"
"github.com/sqshq/sampler/config"
2019-02-26 04:36:23 +00:00
"github.com/sqshq/sampler/console"
"github.com/sqshq/sampler/data"
"image"
)
const (
MinValueLabel = "min"
MaxValueLabel = "max"
CurValueLabel = "cur"
)
2019-07-27 04:15:35 +00:00
// Gauge displays cur value between specified min and max values
2019-02-26 04:36:23 +00:00
type Gauge struct {
2019-03-16 23:59:28 +00:00
*ui.Block
*data.Consumer
minValue float64
maxValue float64
curValue float64
color ui.Color
scale int
percentOnly bool
palette console.Palette
2019-02-26 04:36:23 +00:00
}
func NewGauge(c config.GaugeConfig, palette console.Palette) *Gauge {
g := Gauge{
2021-05-31 16:39:35 +00:00
Block: component.NewBlock(c.Title, *c.Border, palette),
Consumer: data.NewConsumer(),
color: *c.Color,
scale: *c.Scale,
percentOnly: *c.PercentOnly,
palette: palette,
2019-03-08 04:04:46 +00:00
}
go func() {
for {
select {
case sample := <-g.SampleChannel:
g.ConsumeSample(sample)
case alert := <-g.AlertChannel:
g.Alert = alert
}
}
}()
2019-03-08 04:04:46 +00:00
return &g
2019-03-08 04:04:46 +00:00
}
2019-03-16 23:59:28 +00:00
func (g *Gauge) ConsumeSample(sample *data.Sample) {
2019-02-26 04:36:23 +00:00
2019-04-07 18:26:20 +00:00
float, err := util.ParseFloat(sample.Value)
2019-02-26 04:36:23 +00:00
if err != nil {
g.HandleConsumeFailure("Failed to parse a number", err, sample)
2019-03-16 23:59:28 +00:00
return
2019-02-26 04:36:23 +00:00
}
2019-07-28 17:15:34 +00:00
g.HandleConsumeSuccess()
2019-02-26 04:36:23 +00:00
switch sample.Label {
case MinValueLabel:
g.minValue = float
break
case MaxValueLabel:
g.maxValue = float
break
case CurValueLabel:
g.curValue = float
break
}
}
2019-03-16 23:59:28 +00:00
func (g *Gauge) Draw(buffer *ui.Buffer) {
2019-02-26 04:36:23 +00:00
2019-03-16 23:59:28 +00:00
g.Block.Draw(buffer)
2019-02-26 04:36:23 +00:00
percent := calculatePercent(g)
2019-02-26 04:36:23 +00:00
var label string
if g.percentOnly {
label = fmt.Sprintf(" %v%% ", util.FormatValue(percent, g.scale))
} else {
label = fmt.Sprintf(" %v%% (%v) ", util.FormatValue(percent, g.scale), util.FormatValue(g.curValue, g.scale))
}
2019-02-26 04:36:23 +00:00
// draw bar
2019-02-26 04:36:23 +00:00
barWidth := int((percent / 100) * float64(g.Inner.Dx()))
if barWidth == 0 {
barWidth = 1
} else if barWidth > g.Dx()-2 {
barWidth = g.Dx() - 2
}
2019-03-16 23:59:28 +00:00
buffer.Fill(
2019-02-26 04:36:23 +00:00
ui.NewCell(console.SymbolVerticalBar, ui.NewStyle(g.color)),
image.Rect(g.Inner.Min.X+1, g.Inner.Min.Y, g.Inner.Min.X+barWidth, g.Inner.Max.Y),
)
// draw label
2019-02-26 04:36:23 +00:00
labelXCoordinate := g.Inner.Min.X + (g.Inner.Dx() / 2) - int(float64(len(label))/2)
labelYCoordinate := g.Inner.Min.Y + ((g.Inner.Dy() - 1) / 2)
if labelYCoordinate < g.Inner.Max.Y {
for i, char := range label {
style := ui.NewStyle(g.palette.BaseColor)
2019-02-26 04:36:23 +00:00
if labelXCoordinate+i+1 <= g.Inner.Min.X+barWidth {
style = ui.NewStyle(g.palette.BaseColor, ui.ColorClear)
2019-02-26 04:36:23 +00:00
}
2019-03-16 23:59:28 +00:00
buffer.SetCell(ui.NewCell(char, style), image.Pt(labelXCoordinate+i, labelYCoordinate))
2019-02-26 04:36:23 +00:00
}
}
2019-03-16 23:59:28 +00:00
component.RenderAlert(g.Alert, g.Rectangle, buffer)
2019-02-26 04:36:23 +00:00
}
func calculatePercent(g *Gauge) float64 {
if g.curValue != g.minValue && g.maxValue != g.minValue {
return (100 * (g.curValue - g.minValue)) / (g.maxValue - g.minValue)
}
return 0
}