go baby go

This commit is contained in:
2025-09-12 18:58:15 -07:00
parent 95086eafb5
commit 790360ebb5
8 changed files with 458 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
package components
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
const (
BlockEmpty = " "
Block1 = "▁"
Block2 = "▂"
Block3 = "▃"
Block4 = "▄"
Block5 = "▅"
Block6 = "▆"
Block7 = "▇"
Block8 = "█"
)
var blockChars = []string{BlockEmpty, Block1, Block2, Block3, Block4, Block5, Block6, Block7, Block8}
type Chart struct {
Width int
Height int
Data []float64
Title string
style lipgloss.Style
}
func NewChart(data []float64, width, height int, title string) *Chart {
return &Chart{
Data: data,
Width: width,
Height: height,
Title: title,
style: lipgloss.NewStyle().Padding(0, 1),
}
}
func (c *Chart) View() string {
if len(c.Data) == 0 {
return c.style.Render("No data available")
}
min, max := findMinMax(c.Data)
sampled := sampleData(c.Data, c.Width)
var chart strings.Builder
for _, value := range sampled {
normalized := (value - min) / (max - min)
level := int(normalized * 8)
if level > 8 {
level = 8
}
chart.WriteString(blockChars[level])
}
return c.style.Render(fmt.Sprintf("%s\n%s", c.Title, chart.String()))
}
func findMinMax(data []float64) (float64, float64) {
min, max := data[0], data[0]
for _, v := range data {
if v < min {
min = v
}
if v > max {
max = v
}
}
return min, max
}
func sampleData(data []float64, targetLength int) []float64 {
if len(data) <= targetLength {
return data
}
sampled := make([]float64, targetLength)
ratio := float64(len(data)) / float64(targetLength)
for i := 0; i < targetLength; i++ {
index := int(float64(i) * ratio)
if index >= len(data) {
index = len(data) - 1
}
sampled[i] = data[index]
}
return sampled
}

View File

@@ -0,0 +1,38 @@
package components
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestChartView(t *testing.T) {
t.Run("empty data", func(t *testing.T) {
chart := NewChart(nil, 10, 4, "Test")
view := chart.View()
assert.Contains(t, view, "No data available")
})
t.Run("single data point", func(t *testing.T) {
chart := NewChart([]float64{50}, 5, 4, "Single")
view := chart.View()
assert.Equal(t, "Single\n▄▄▄▄▄", view)
})
t.Run("multiple data points", func(t *testing.T) {
data := []float64{10, 20, 30, 40, 50}
chart := NewChart(data, 5, 4, "Series")
view := chart.View()
assert.Equal(t, "Series\n▁▂▄▆█", view)
})
t.Run("downsampling", func(t *testing.T) {
data := make([]float64, 100)
for i := range data {
data[i] = float64(i)
}
chart := NewChart(data, 20, 4, "Downsample")
view := chart.View()
assert.Len(t, view, 20+6) // Title + chart characters
})
}