Skip to content

Commit

Permalink
(feat) better bar charts
Browse files Browse the repository at this point in the history
  • Loading branch information
kevincobain2000 committed Dec 26, 2023
1 parent 31ecf63 commit 96435f0
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 75 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ https://instachart.coveritup.app/line?title=Continuous+Series&x_label=No+of+peop
| :----------- | :------- | :---------- | :--------------------------------------------------- |
| `data` || JSON | `?data={ "x": [["Mon","Tue","Wed"]],"y": [[1,2,3]]}` |
| `title` | | string | |
| `y_label` | | string | |
| `base_value` | | int | |
| `subtitle` | | string | |
| `height` | | int | |
| `width` | | int | |

Expand All @@ -152,7 +151,7 @@ https://instachart.coveritup.app/line?title=Continuous+Series&x_label=No+of+peop
```sh
https://instachart.coveritup.app/bar?title=Bar+Chart&y_label=Sleeping+hours&data={
"x": ["Monday", "Friday", "Sunday"],
"y": [8, 2 ,14]
"y": [[8, 2 ,14]]
}
```

Expand Down Expand Up @@ -247,12 +246,13 @@ https://instachart.coveritup.app/pie?title=Pie+Chart&subtitle=Sleeping+Hours&dat
## [`GET /radar`](https://instachart.coveritup.app/radar?title=Pie+Chart&subtitle=Sleeping+Hours&data={%20"names":%20["Monday",%20"Friday",%20"Saturday",%20"Sunday"],%20"values":%20[4,%206%20,7,%209]%20})


| Query | Required | Description | Example |
| :------- | :------- | :---------- | :--------------------------------------------------------------------------------------- |
| `data` || JSON | `data={"names": ["Mon","Tue", "Wed"], "labels": ["Work", "Relax"], "values": [[1,2,4]]}` |
| `title` | | string | |
| `height` | | int | |
| `width` | | int | |
| Query | Required | Description | Example |
| :--------- | :------- | :---------- | :--------------------------------------------------------------------------------------- |
| `data` || JSON | `data={"names": ["Mon","Tue", "Wed"], "labels": ["Work", "Relax"], "values": [[1,2,4]]}` |
| `title` | | string | |
| `subtitle` | | string | |
| `height` | | int | |
| `width` | | int | |


| `data` | Required | Description | Example | Valid |
Expand Down
28 changes: 0 additions & 28 deletions pkg/bar_chart.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package pkg

import (
"github.com/wcharczuk/go-chart/v2"
)

type BarChart struct {
chart *Chart
}
Expand All @@ -13,27 +9,3 @@ func NewBarChart() *BarChart {
chart: NewChart(),
}
}

func (c *BarChart) GetBackground() chart.Style {
return c.chart.GetBackground()
}
func (c *BarChart) GetValues(xData []string, yData []float64) []chart.Value {
var values []chart.Value
min := yData[0]
max := yData[0]
sum := 0.0
for i := 0; i < len(xData); i++ {
sum += yData[i]
values = append(values, chart.Value{
Value: yData[i],
Label: xData[i],
})
if yData[i] < min {
min = yData[i]
}
if yData[i] > max {
max = yData[i]
}
}
return values
}
94 changes: 62 additions & 32 deletions pkg/bar_chart_handler.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package pkg

import (
"bytes"
"encoding/json"
"net/http"

"github.com/labstack/echo/v4"
"github.com/wcharczuk/go-chart/v2"
charts "github.com/vicanso/go-charts/v2"
)

type BarChartHandler struct {
Expand All @@ -20,17 +19,19 @@ func NewBarChartHandler() *BarChartHandler {
}

type BarChartRequest struct {
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
YAxisLabel string `json:"y_label" query:"y_label" form:"y_label"`
ChartTitle string `json:"title" query:"title" form:"title"`
BaseValue float64 `json:"base_value" query:"base_value" form:"base_value"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
ChartTitle string `json:"title" query:"title" form:"title"`
ChartSubtitle string `json:"subtitle" query:"subtitle" form:"subtitle"`
BaseValue float64 `json:"base_value" query:"base_value" form:"base_value"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
Horizontal bool `json:"horizontal" query:"horizontal" form:"horizontal"`
}

type BarChartData struct {
XData []string `json:"x"`
YData []float64 `json:"y"`
XData []string `json:"x"`
YData [][]float64 `json:"y"`
Names []string `json:"names"`
}

func (h *BarChartHandler) Get(c echo.Context) ([]byte, error) {
Expand All @@ -44,35 +45,64 @@ func (h *BarChartHandler) Get(c echo.Context) ([]byte, error) {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}

if len(data.XData) == 0 || len(data.XData) != len(data.YData) {
if len(data.XData) == 0 || len(data.XData) != len(data.YData[0]) {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, "data provided is invalid")
}

baseValue := req.BaseValue
useBaseValue := false
if baseValue > 0.0 {
baseValue = req.BaseValue
useBaseValue = true
if len(data.YData) == 1 && !req.Horizontal {
// append [0,0,...0] to data.YData
data.YData = append(data.YData, make([]float64, len(data.YData[0])))
}

graph := chart.BarChart{
Title: req.ChartTitle,
Height: req.Height,
Width: req.Width,
Background: h.chart.GetBackground(),
YAxis: chart.YAxis{
Name: req.YAxisLabel,
AxisType: chart.YAxisSecondary,
},
UseBaseValue: useBaseValue,
BaseValue: baseValue,
Bars: h.chart.GetValues(data.XData, data.YData),
if !req.Horizontal {
p, err := charts.BarRender(
data.YData,
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: 9,
Left: charts.PositionCenter,
}),
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.XAxisDataOptionFunc(data.XData),
charts.LegendLabelsOptionFunc(data.Names, charts.PositionRight),
charts.MarkLineOptionFunc(0, charts.SeriesMarkDataTypeAverage),
charts.MarkPointOptionFunc(0, charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin),
func(opt *charts.ChartOption) {
opt.SeriesList[1].MarkPoint = charts.NewMarkPoint(
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
)
opt.SeriesList[1].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
},
)
if err != nil {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
buf, err := p.Bytes()
return buf, err
}

buffer := bytes.NewBuffer([]byte{})
err := graph.Render(chart.PNG, buffer)
p, err := charts.HorizontalBarRender(
data.YData,
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
SubtextFontSize: 9,
Left: charts.PositionCenter,
}),
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.YAxisDataOptionFunc(data.XData),
)

if err != nil {
return nil, echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
return buffer.Bytes(), err

buf, err := p.Bytes()
return buf, err
}
6 changes: 5 additions & 1 deletion pkg/bar_chart_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ func TestGetBarChart(t *testing.T) {
}
testCases := []TestCase{
{
QueryParams: `{"x": ["2022-12-23","2022-12-28","2023-12-30"], "y": [1,2,3]}`,
QueryParams: `{"x": ["2022-12-23","2022-12-28","2023-12-30"], "y": [[1,2,3]]}`,
ExpectedStatus: http.StatusOK,
},
{
QueryParams: `{"x": ["2022-12-23","2022-12-28","2023-12-30"], "y": [1,2,3]}`,
ExpectedStatus: http.StatusUnprocessableEntity,
},
{
QueryParams: `{"x": ["2022-12-23,"2022-12-28","2023-12-30"], "y": [1,2,3]}`,
ExpectedStatus: http.StatusUnprocessableEntity,
Expand Down
15 changes: 10 additions & 5 deletions pkg/radar_chart_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ func NewRadarChartHandler() *RadarChartHandler {
}

type RadarChartRequest struct {
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
ChartTitle string `json:"title" query:"title" form:"title"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
ChartData string `json:"data" query:"data" form:"data" validate:"required" message:"data is required"`
ChartTitle string `json:"title" query:"title" form:"title"`
ChartSubtitle string `json:"subtitle" query:"subtitle" form:"subtitle"`
Height int `json:"height" query:"height" form:"height"`
Width int `json:"width" query:"width" form:"width"`
}

type RadarChartData struct {
Expand All @@ -49,9 +50,13 @@ func (h *RadarChartHandler) Get(c echo.Context) ([]byte, error) {

graph, err := charts.RadarRender(
data.Values,
charts.TitleOptionFunc(charts.TitleOption{
Text: req.ChartTitle,
Subtext: req.ChartSubtitle,
Left: charts.PositionCenter,
}),
charts.HeightOptionFunc(req.Height),
charts.WidthOptionFunc(req.Width),
charts.TitleTextOptionFunc(req.ChartTitle),
charts.LegendLabelsOptionFunc(data.Labels),
charts.RadarIndicatorOptionFunc(data.Names, h.chart.GetIndicators(data.Values)),
)
Expand Down

0 comments on commit 96435f0

Please sign in to comment.