sampler-fork/component/runchart/legend.go

115 lines
2.7 KiB
Go
Raw Permalink Normal View History

2019-02-15 04:34:45 +00:00
package runchart
import (
"fmt"
2019-03-14 03:01:44 +00:00
ui "github.com/gizak/termui/v3"
2019-03-26 03:29:23 +00:00
"github.com/sqshq/sampler/component/util"
2019-02-15 04:34:45 +00:00
"image"
"math"
)
const (
xAxisLegendIndent = 10
yAxisLegendIndent = 1
heightOnDefault = 2
heightOnPinpoint = 4
heightOnDetails = 6
2019-02-16 02:52:03 +00:00
timeFormat = "15:04:05.000"
2019-02-15 04:34:45 +00:00
)
2019-07-27 04:15:35 +00:00
type legend struct {
2019-02-15 04:34:45 +00:00
Enabled bool
Details bool
}
func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
if !c.legend.Enabled {
return
}
height := heightOnDefault
if c.mode == ModePinpoint {
height = heightOnPinpoint
} else if c.legend.Details {
height = heightOnDetails
2019-02-15 04:34:45 +00:00
}
2019-02-16 03:46:03 +00:00
rowCount := (c.Dy() - 2*yAxisLegendIndent) / (height + yAxisLegendIndent)
2019-02-15 04:34:45 +00:00
columnCount := int(math.Ceil(float64(len(c.lines)) / float64(rowCount)))
2019-02-19 04:07:32 +00:00
columnWidth := getColumnWidth(c.mode, c.lines, c.scale)
2019-02-15 04:34:45 +00:00
for col := 0; col < columnCount; col++ {
for row := 0; row < rowCount; row++ {
lineIndex := row + rowCount*col
if len(c.lines) <= lineIndex {
break
}
line := c.lines[row+rowCount*col]
2019-02-15 04:34:45 +00:00
x := c.Inner.Max.X - (columnWidth+xAxisLegendIndent)*(col+1)
y := c.Inner.Min.Y + yAxisLegendIndent + row*height
2019-02-15 04:34:45 +00:00
titleStyle := ui.NewStyle(line.color)
detailsStyle := ui.NewStyle(c.palette.BaseColor)
2019-02-15 04:34:45 +00:00
buffer.SetString(string(ui.DOT), titleStyle, image.Pt(x-2, y))
buffer.SetString(line.label, titleStyle, image.Pt(x, y))
if c.mode == ModePinpoint {
2019-02-16 02:52:03 +00:00
buffer.SetString(fmt.Sprintf("time %s", line.selectionPoint.time.Format("15:04:05.000")), detailsStyle, image.Pt(x, y+1))
2019-03-26 03:29:23 +00:00
buffer.SetString(fmt.Sprintf("value %s", util.FormatValue(line.selectionPoint.value, c.scale)), detailsStyle, image.Pt(x, y+2))
continue
}
2019-02-15 04:34:45 +00:00
if !c.legend.Details {
continue
}
details := [4]string{
2019-03-26 03:29:23 +00:00
fmt.Sprintf("cur %s", util.FormatValue(getCurrentValue(line), c.scale)),
2019-06-13 03:35:12 +00:00
fmt.Sprintf("dlt %s", util.FormatDelta(getDiffWithPreviousValue(line), c.scale)),
2019-03-26 03:29:23 +00:00
fmt.Sprintf("max %s", util.FormatValue(line.extrema.max, c.scale)),
fmt.Sprintf("min %s", util.FormatValue(line.extrema.min, c.scale)),
2019-02-15 04:34:45 +00:00
}
for i, detail := range details {
buffer.SetString(detail, detailsStyle, image.Pt(x, y+i+yAxisLegendIndent))
}
}
}
}
2019-02-19 04:07:32 +00:00
func getColumnWidth(mode Mode, lines []TimeLine, scale int) int {
2019-02-16 02:52:03 +00:00
if mode == ModePinpoint {
return len(timeFormat)
}
2019-03-26 03:29:23 +00:00
width := len(util.FormatValue(0, scale))
2019-02-15 04:34:45 +00:00
for _, line := range lines {
if len(line.label) > width {
width = len(line.label)
}
}
return width
}
2019-02-16 02:52:03 +00:00
func getDiffWithPreviousValue(line TimeLine) float64 {
if len(line.points) < 2 {
return 0
2019-02-15 04:34:45 +00:00
}
2019-07-27 04:15:35 +00:00
return line.points[len(line.points)-1].value - line.points[len(line.points)-2].value
2019-02-16 02:52:03 +00:00
}
2019-02-15 04:34:45 +00:00
2019-02-16 02:52:03 +00:00
func getCurrentValue(line TimeLine) float64 {
2019-02-17 23:00:00 +00:00
if len(line.points) == 0 {
return 0
}
2019-07-27 04:15:35 +00:00
return line.points[len(line.points)-1].value
2019-02-15 04:34:45 +00:00
}