aeus-admin/pkg/chartjs/counter.go

79 lines
1.6 KiB
Go

package chartjs
import (
"slices"
"sync"
)
// DataCounter 计数统计, 实现类似Pie 和 Doughnut 之类的图形
type DataCounter struct {
mutex sync.Mutex
legends map[string]*counterValue
}
func (c *DataCounter) Inc(leg string, label string, value float64) {
c.mutex.Lock()
defer c.mutex.Unlock()
v, ok := c.legends[leg]
if !ok {
v = &counterValue{
Label: leg,
Values: make(map[string]float64),
}
c.legends[leg] = v
}
v.Values[label] += value
}
func (c *DataCounter) Dec(legend string, label string, value float64) {
c.mutex.Lock()
defer c.mutex.Unlock()
v, ok := c.legends[legend]
if !ok {
return
}
if _, ok := v.Values[label]; ok {
v.Values[label] -= value
}
}
func (c *DataCounter) Data() *CounterData {
c.mutex.Lock()
defer c.mutex.Unlock()
data := &CounterData{
Lables: make([]string, 0, 5),
Datasets: make([]*CounterValue, 0, len(c.legends)),
}
for _, row := range c.legends {
for k, _ := range row.Values {
if !slices.Contains(data.Lables, k) {
data.Lables = append(data.Lables, k)
}
}
}
for _, row := range c.legends {
set := &CounterValue{
Label: row.Label,
Data: make([]float64, 0, len(data.Lables)),
}
for _, label := range data.Lables {
set.Data = append(set.Data, row.Values[label])
}
data.Datasets = append(data.Datasets, set)
}
return data
}
func NewDataCounter(legends ...string) *DataCounter {
c := &DataCounter{
legends: make(map[string]*counterValue),
}
for _, legend := range legends {
c.legends[legend] = &counterValue{
Label: legend,
Values: make(map[string]float64),
}
}
return c
}