column_chart.gno
2.63 Kb ยท 105 lines
1package charts
2
3import (
4 "strings"
5
6 "gno.land/p/nt/ufmt"
7)
8
9// GenerateColumnChart creates an ASCII column chart in markdown format
10// values: slice of float values to chart
11// maxColumns: maximum number of columns to display (will normalize if exceeded)
12// title: chart title
13// xAxisTitle: title for the x-axis
14// yAxisTitle: title for the y-axis
15// Returns a markdown string representing the chart
16func GenerateColumnChart(values []float64, maxColumns int, title, xAxisTitle, yAxisTitle string) string {
17 if len(values) == 0 {
18 return "no data to display"
19 }
20
21 if maxColumns <= 0 {
22 return "maxColumns must be greater than 0"
23 }
24
25 maxVal := findMaxValue(values)
26
27 displayValues := values
28 if len(values) > maxColumns {
29 displayValues = normalizeData(values, maxColumns)
30 }
31
32 scale := height / maxVal
33
34 output := formatChartHeader(title)
35 output += "\n```\n"
36 output += formatYAxisTitle(yAxisTitle)
37
38 maxYValue := ufmt.Sprintf("%.2f", maxVal)
39 yAxisWidth := len(maxYValue)
40
41 maxValStrLen := calculateMaxValueStringLength(displayValues)
42 if maxValStrLen < 2 {
43 maxValStrLen = 2
44 }
45 colWidth := maxValStrLen + 2
46
47 for row := height; row > 0; row-- {
48 if row%3 == 0 {
49 output += formatYAxisLabel(float64(row), scale, yAxisWidth)
50 } else {
51 output += formatYAxisSpace(yAxisWidth)
52 }
53
54 for _, val := range displayValues {
55 scaledHeight := int(val * scale)
56 if scaledHeight >= row {
57 barWidth := colWidth - 1
58 output += strings.Repeat("|", barWidth) + " "
59 } else {
60 output += strings.Repeat(" ", colWidth)
61 }
62 }
63 output += "\n"
64 }
65
66 output += strings.Repeat(" ", yAxisWidth) + " +"
67 output += strings.Repeat(strings.Repeat("-", colWidth), len(displayValues))
68 output += "\n"
69
70 output += formatValueLabelsColumnChart(displayValues, colWidth, yAxisWidth)
71
72 if xAxisTitle != "" {
73 totalWidth := len(displayValues) * colWidth
74 output += formatXAxisTitle(xAxisTitle, totalWidth)
75 }
76
77 output += "```\n"
78 return output
79}
80
81// formatValueLabelsColumnChart formats the value labels for the x-axis for column charts
82func formatValueLabelsColumnChart(values []float64, colWidth int, yAxisWidth int) string {
83 output := strings.Repeat(" ", yAxisWidth+2)
84
85 for i := 0; i < len(values); i++ {
86 x := i * colWidth
87 valStr := ufmt.Sprintf("%.2f", values[i])
88 labelPos := x + colWidth/2 - len(valStr)/2
89 if labelPos < 0 {
90 labelPos = 0
91 }
92
93 if i == 0 {
94 output += strings.Repeat(" ", labelPos)
95 } else {
96 prevX := (i - 1) * colWidth
97 prevValStr := ufmt.Sprintf("%.2f", values[i-1])
98 prevLabelEnd := prevX + colWidth/2 - len(prevValStr)/2 + len(prevValStr)
99 output += strings.Repeat(" ", labelPos-prevLabelEnd)
100 }
101 output += valStr
102 }
103
104 return output + "\n"
105}