feat: initial release v0.3.0
- Support 9 chart types: line, bar, pie, scatter, bubble, donut, mixed, polar, radar - Multi-format output: ANSI, SVG, PNG, Markdown - Go + Fiber + gonum/plot - Docker support - Morandi color palette
This commit is contained in:
85
internal/service/chart.go
Normal file
85
internal/service/chart.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/picoclaw/chart/internal/renderer"
|
||||
"github.com/picoclaw/chart/internal/types"
|
||||
)
|
||||
|
||||
type ChartService struct {
|
||||
svgRenderer *renderer.SVGRenderer
|
||||
pngRenderer *renderer.PNGRenderer
|
||||
ansiRenderer *renderer.ANSIRenderer
|
||||
textRenderer *renderer.TextRenderer
|
||||
chartCache map[string]*types.Chart
|
||||
}
|
||||
|
||||
func NewChartService() *ChartService {
|
||||
return &ChartService{
|
||||
svgRenderer: renderer.NewSVGRenderer(),
|
||||
pngRenderer: renderer.NewPNGRenderer(),
|
||||
ansiRenderer: renderer.NewANSIRenderer(),
|
||||
textRenderer: renderer.NewTextRenderer(),
|
||||
chartCache: make(map[string]*types.Chart),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ChartService) CreateChart(req *types.ChartRequest) (*types.ChartResponse, error) {
|
||||
chart := &types.Chart{
|
||||
ID: uuid.New().String(),
|
||||
Type: req.Type,
|
||||
Title: req.Title,
|
||||
Data: req.Data,
|
||||
}
|
||||
|
||||
svgData, err := s.svgRenderer.Render(chart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to render SVG: %w", err)
|
||||
}
|
||||
chart.SVG = svgData
|
||||
|
||||
pngData, err := s.pngRenderer.Render(chart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to render PNG: %w", err)
|
||||
}
|
||||
chart.PNG = pngData
|
||||
|
||||
ansiData, err := s.ansiRenderer.Render(chart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to render ANSI: %w", err)
|
||||
}
|
||||
|
||||
textData, err := s.textRenderer.Render(chart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to render text: %w", err)
|
||||
}
|
||||
|
||||
s.chartCache[chart.ID] = chart
|
||||
|
||||
return &types.ChartResponse{
|
||||
ChartID: chart.ID,
|
||||
Text: string(textData),
|
||||
ANSI: string(ansiData),
|
||||
SVG: string(chart.SVG),
|
||||
PNGURL: fmt.Sprintf("/api/v1/chart/%s.png", chart.ID),
|
||||
Markdown: fmt.Sprintf("", chart.Title, chart.ID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *ChartService) GetChart(id string) (*types.Chart, error) {
|
||||
chart, ok := s.chartCache[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("chart not found: %s", id)
|
||||
}
|
||||
return chart, nil
|
||||
}
|
||||
|
||||
func (s *ChartService) GetChartPNG(id string) ([]byte, error) {
|
||||
chart, err := s.GetChart(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chart.PNG, nil
|
||||
}
|
||||
Reference in New Issue
Block a user