added legend values calculation

This commit is contained in:
sqshq 2019-02-15 21:52:03 -05:00
parent 88a935d6d3
commit 1b7f851174
3 changed files with 57 additions and 46 deletions

View File

@ -20,7 +20,7 @@ runcharts:
beep: true beep: true
legend: legend:
enabled: true enabled: true
details: false details: true
position: position:
x: 0 x: 0
y: 0 y: 0
@ -47,7 +47,7 @@ runcharts:
beep: true beep: true
legend: legend:
enabled: true enabled: true
details: true details: false
position: position:
x: 0 x: 0
y: 15 y: 15

View File

@ -13,6 +13,8 @@ const (
heightOnDefault = 2 heightOnDefault = 2
heightOnPinpoint = 4 heightOnPinpoint = 4
heightOnDetails = 6 heightOnDetails = 6
timeFormat = "15:04:05.000"
) )
type Legend struct { type Legend struct {
@ -36,7 +38,7 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
rowCount := (c.Dx() - yAxisLegendIndent) / (height + yAxisLegendIndent) rowCount := (c.Dx() - yAxisLegendIndent) / (height + yAxisLegendIndent)
columnCount := int(math.Ceil(float64(len(c.lines)) / float64(rowCount))) columnCount := int(math.Ceil(float64(len(c.lines)) / float64(rowCount)))
columnWidth := getColumnWidth(c.lines, c.precision) columnWidth := getColumnWidth(c.mode, c.lines, c.precision)
for col := 0; col < columnCount; col++ { for col := 0; col < columnCount; col++ {
for row := 0; row < rowCount; row++ { for row := 0; row < rowCount; row++ {
@ -47,7 +49,6 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
} }
line := c.lines[row+rowCount*col] line := c.lines[row+rowCount*col]
extrema := getLineValueExtrema(line.points)
x := c.Inner.Max.X - (columnWidth+xAxisLegendIndent)*(col+1) x := c.Inner.Max.X - (columnWidth+xAxisLegendIndent)*(col+1)
y := c.Inner.Min.Y + yAxisLegendIndent + row*height y := c.Inner.Min.Y + yAxisLegendIndent + row*height
@ -59,6 +60,8 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
buffer.SetString(line.label, titleStyle, image.Pt(x, y)) buffer.SetString(line.label, titleStyle, image.Pt(x, y))
if c.mode == ModePinpoint { if c.mode == ModePinpoint {
buffer.SetString(fmt.Sprintf("time %s", line.selectionPoint.time.Format("15:04:05.000")), detailsStyle, image.Pt(x, y+1))
buffer.SetString(fmt.Sprintf("value %s", formatValue(line.selectionPoint.value, c.precision)), detailsStyle, image.Pt(x, y+2))
continue continue
} }
@ -67,10 +70,10 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
} }
details := [4]string{ details := [4]string{
fmt.Sprintf("cur %s", formatValue(line.points[len(line.points)-1].value, c.precision)), fmt.Sprintf("cur %s", formatValue(getCurrentValue(line), c.precision)),
fmt.Sprintf("max %s", formatValue(extrema.max, c.precision)), fmt.Sprintf("max %s", formatValue(line.extrema.max, c.precision)),
fmt.Sprintf("min %s", formatValue(extrema.min, c.precision)), fmt.Sprintf("min %s", formatValue(line.extrema.min, c.precision)),
fmt.Sprintf("dif %s", formatValue(1, c.precision)), fmt.Sprintf("dif %s", formatValue(getDiffWithPreviousValue(line), c.precision)),
} }
for i, detail := range details { for i, detail := range details {
@ -80,7 +83,12 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
} }
} }
func getColumnWidth(lines []TimeLine, precision int) int { func getColumnWidth(mode Mode, lines []TimeLine, precision int) int {
if mode == ModePinpoint {
return len(timeFormat)
}
width := len(formatValue(0, precision)) width := len(formatValue(0, precision))
for _, line := range lines { for _, line := range lines {
if len(line.label) > width { if len(line.label) > width {
@ -90,23 +98,14 @@ func getColumnWidth(lines []TimeLine, precision int) int {
return width return width
} }
// TODO remove and use the one from line func getDiffWithPreviousValue(line TimeLine) float64 {
func getLineValueExtrema(points []TimePoint) ValueExtrema { if len(line.points) < 2 {
return 0
if len(points) == 0 { } else {
return ValueExtrema{0, 0} return math.Abs(line.points[len(line.points)-1].value - line.points[len(line.points)-2].value)
} }
}
var max, min = -math.MaxFloat64, math.MaxFloat64
func getCurrentValue(line TimeLine) float64 {
for _, point := range points { return line.points[len(line.points)-1].value
if point.value > max {
max = point.value
}
if point.value < min {
min = point.value
}
}
return ValueExtrema{max: max, min: min}
} }

View File

@ -53,11 +53,12 @@ type TimePoint struct {
} }
type TimeLine struct { type TimeLine struct {
points []TimePoint points []TimePoint
extrema ValueExtrema extrema ValueExtrema
color ui.Color color ui.Color
label string label string
selection int selectionCoordinate int
selectionPoint TimePoint
} }
type TimeRange struct { type TimeRange struct {
@ -130,15 +131,25 @@ func (c *RunChart) ConsumeSample(sample data.Sample) {
if lineIndex == -1 { if lineIndex == -1 {
line := &TimeLine{ line := &TimeLine{
points: []TimePoint{}, points: []TimePoint{},
color: sample.Color, color: sample.Color,
label: sample.Label, label: sample.Label,
extrema: ValueExtrema{max: float, min: float},
} }
c.lines = append(c.lines, *line) c.lines = append(c.lines, *line)
lineIndex = len(c.lines) - 1 lineIndex = len(c.lines) - 1
} }
line := c.lines[lineIndex] line := c.lines[lineIndex]
if float < line.extrema.min {
line.extrema.min = float
}
if float > line.extrema.max {
line.extrema.max = float
}
timePoint := c.newTimePoint(float) timePoint := c.newTimePoint(float)
line.points = append(line.points, timePoint) line.points = append(line.points, timePoint)
c.lines[lineIndex] = line c.lines[lineIndex] = line
@ -167,9 +178,10 @@ func (c *RunChart) renderLines(buffer *ui.Buffer, drawArea image.Rectangle) {
xPoint := make(map[int]image.Point) xPoint := make(map[int]image.Point)
xOrder := make([]int, 0) xOrder := make([]int, 0)
if line.selection != 0 { // move selection on a delta, if it was instantiated after cursor move
line.selection -= delta if line.selectionCoordinate != 0 {
c.lines[i].selection = line.selection line.selectionCoordinate -= delta
c.lines[i].selectionCoordinate = line.selectionCoordinate
} }
for j, timePoint := range line.points { for j, timePoint := range line.points {
@ -195,14 +207,14 @@ func (c *RunChart) renderLines(buffer *ui.Buffer, drawArea image.Rectangle) {
continue continue
} }
if line.selection == 0 { if line.selectionCoordinate == 0 {
// instantiate selection coordinate as the closest point to the cursor time
if len(line.points) > j+1 && ui.AbsInt(timePoint.coordinate-selectionCoordinate) > ui.AbsInt(line.points[j+1].coordinate-selectionCoordinate) { if len(line.points) > j+1 && ui.AbsInt(timePoint.coordinate-selectionCoordinate) > ui.AbsInt(line.points[j+1].coordinate-selectionCoordinate) {
selectionPoints[i] = point selectionPoints[i] = point
c.lines[i].selectionPoint = timePoint
} }
} else { } else if timePoint.coordinate == line.selectionCoordinate {
if timePoint.coordinate == line.selection { selectionPoints[i] = point
selectionPoints[i] = point
}
} }
xPoint[point.X] = point xPoint[point.X] = point
@ -233,8 +245,8 @@ func (c *RunChart) renderLines(buffer *ui.Buffer, drawArea image.Rectangle) {
if c.mode == ModePinpoint { if c.mode == ModePinpoint {
for lineIndex, point := range selectionPoints { for lineIndex, point := range selectionPoints {
buffer.SetCell(ui.NewCell(console.SymbolSelection, ui.NewStyle(c.lines[lineIndex].color)), point) buffer.SetCell(ui.NewCell(console.SymbolSelection, ui.NewStyle(c.lines[lineIndex].color)), point)
if c.lines[lineIndex].selection == 0 { if c.lines[lineIndex].selectionCoordinate == 0 {
c.lines[lineIndex].selection = point.X c.lines[lineIndex].selectionCoordinate = point.X
} }
} }
} }
@ -299,7 +311,7 @@ func (c *RunChart) MoveSelection(shift int) {
} }
for i := range c.lines { for i := range c.lines {
c.lines[i].selection = 0 c.lines[i].selectionCoordinate = 0
} }
} }