primeiro commit
This commit is contained in:
113
internal/ui/graph.go
Normal file
113
internal/ui/graph.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type rateSample struct {
|
||||
inBitsPerSecond float64
|
||||
outBitsPerSecond float64
|
||||
}
|
||||
|
||||
// RateGraph draws inbound and outbound bit-rate history.
|
||||
type RateGraph struct {
|
||||
*tview.Box
|
||||
mu sync.Mutex
|
||||
samples []rateSample
|
||||
maxSamples int
|
||||
}
|
||||
|
||||
// NewRateGraph creates a graph primitive with bounded history.
|
||||
func NewRateGraph(maxSamples int) *RateGraph {
|
||||
graph := &RateGraph{
|
||||
Box: tview.NewBox().SetBorder(true).SetTitle(" Interface traffic "),
|
||||
maxSamples: maxSamples,
|
||||
}
|
||||
return graph
|
||||
}
|
||||
|
||||
// AddSample appends one inbound/outbound sample to the graph.
|
||||
func (g *RateGraph) AddSample(inBitsPerSecond float64, outBitsPerSecond float64) {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
g.samples = append(g.samples, rateSample{
|
||||
inBitsPerSecond: inBitsPerSecond,
|
||||
outBitsPerSecond: outBitsPerSecond,
|
||||
})
|
||||
if len(g.samples) > g.maxSamples {
|
||||
g.samples = g.samples[len(g.samples)-g.maxSamples:]
|
||||
}
|
||||
}
|
||||
|
||||
// Draw renders the graph primitive.
|
||||
func (g *RateGraph) Draw(screen tcell.Screen) {
|
||||
g.Box.DrawForSubclass(screen, g)
|
||||
x, y, width, height := g.GetInnerRect()
|
||||
if width <= 0 || height <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
samples := g.copySamples()
|
||||
if len(samples) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
maxRate := maxSampleRate(samples)
|
||||
if maxRate <= 0 {
|
||||
maxRate = 1
|
||||
}
|
||||
|
||||
label := "in: green out: blue"
|
||||
for i, r := range label {
|
||||
if i >= width {
|
||||
break
|
||||
}
|
||||
screen.SetContent(x+i, y, r, nil, tcell.StyleDefault.Foreground(tcell.ColorGray))
|
||||
}
|
||||
|
||||
start := 0
|
||||
if len(samples) > width {
|
||||
start = len(samples) - width
|
||||
}
|
||||
plotHeight := height - 1
|
||||
for col, sample := range samples[start:] {
|
||||
drawPoint(screen, x+col, y+1, plotHeight, sample.inBitsPerSecond, maxRate, tcell.ColorGreen)
|
||||
drawPoint(screen, x+col, y+1, plotHeight, sample.outBitsPerSecond, maxRate, tcell.ColorDodgerBlue)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *RateGraph) copySamples() []rateSample {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
samples := make([]rateSample, len(g.samples))
|
||||
copy(samples, g.samples)
|
||||
return samples
|
||||
}
|
||||
|
||||
func maxSampleRate(samples []rateSample) float64 {
|
||||
var maxRate float64
|
||||
for _, sample := range samples {
|
||||
maxRate = math.Max(maxRate, sample.inBitsPerSecond)
|
||||
maxRate = math.Max(maxRate, sample.outBitsPerSecond)
|
||||
}
|
||||
return maxRate
|
||||
}
|
||||
|
||||
func drawPoint(screen tcell.Screen, x int, y int, height int, value float64, maxRate float64, color tcell.Color) {
|
||||
if height <= 0 {
|
||||
return
|
||||
}
|
||||
ratio := value / maxRate
|
||||
if ratio < 0 {
|
||||
ratio = 0
|
||||
}
|
||||
if ratio > 1 {
|
||||
ratio = 1
|
||||
}
|
||||
row := height - 1 - int(math.Round(ratio*float64(height-1)))
|
||||
screen.SetContent(x, y+row, '●', nil, tcell.StyleDefault.Foreground(color))
|
||||
}
|
||||
Reference in New Issue
Block a user