每次刷新都实时解析路由中给出的 .chart 文件.

Signed-off-by: lion.chan <cy187lion@sina.com>
This commit is contained in:
lion.chan 2022-08-31 15:37:09 +08:00
parent e9103b47a6
commit 15e7b02ed1
8 changed files with 86 additions and 81 deletions

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"cwd": "./examples",
"program": "${fileDirname}"
}
]
}

View File

@ -1,9 +1,8 @@
goplot
======
# goplot
goplot 是一个使用简单的绘制图表的工具,图表绘制使用了[Chart.js](http://www.chartjs.org/)开源库编译好的goplot只有一个二进制文件不依赖任何库/网络。
##### 下载
## 下载
[Mac OS X](http://www.bigendian123.com/goplot-darwin.tar.gz)
@ -11,23 +10,32 @@ goplot 是一个使用简单的绘制图表的工具,图表绘制使用了[Cha
Windows暂缺
##### 使用方法
## 使用方法
* 解压下载包后,进入解压目录,可以看到一个 goplot 的可执行文件和一些 *.chart 文件,这些 chart 文件是默认的一些数据文件样例。可以在这些 chart 文件的目录执行 goplot然后通过浏览器访问<http://localhost:8000> 就可以看到图表了。
* 你可以把 `goplot` 工具放到你的 `PATH` 中,在 chart 文件所在的目录执行 goplot 即可。
* chart 文件必须是 .chart 后缀名,内容可以参考源码 examples 目录中的例子。启动 goplot 的目录如果有多个 chart 文件,可以通过不断刷新网页来切换图表。
.chart 文件定义了 Chart 的 Namegoplot 会根据该 Name 建立路由规则,访问对应 Name 的 Chart 规则为:
.chart 文件定义了 Chart 的 Type可以为以下字符串
* line
* bar
* pie
goplot 根据路由来匹配 .chart 文件URL 一级名称即为需要解析的 .chart 文件名(路由中不包含扩展名部分)
```url
http://localhost:8000/\<Chart Name>
http://localhost:8000/\<Chart File Name>
```
##### 曲线图
![](image/line.png)
## 曲线图
##### 柱状图
![](image/bar.png)
![line](image/line.png)
##### 饼图
![](image/pie.png)
## 柱状图
![bar](image/bar.png)
## 饼图
![pie](image/pie.png)

42
data.go
View File

@ -8,13 +8,14 @@ import (
"io"
"log"
"os"
"path/filepath"
"strconv"
"strings"
)
type ParseState int
const (
START = iota
START ParseState = iota
PROP
DATA
)
@ -25,9 +26,9 @@ var (
)
type ChartPropType struct {
Name string
Width int
Height int
Type string `json:"Type"`
Width int `json:"Width"`
Height int `json:"Height"`
}
type ChartItemType struct {
@ -146,20 +147,20 @@ func ParseDataFile(file string) ([]*ChartDataType, error) {
switch status {
case START:
if bytes.Compare(line, prop_header_str) == 0 {
if bytes.Equal(line, prop_header_str) {
status = PROP
c = newChartData()
} else {
return nil, errors.New("invalid chart file")
}
case PROP:
if bytes.Compare(line, data_header_str) == 0 {
if bytes.Equal(line, data_header_str) {
status = DATA
} else {
c.appendProp(line)
}
case DATA:
if bytes.Compare(line, prop_header_str) == 0 {
if bytes.Equal(line, prop_header_str) {
status = PROP
charts = append(charts, c)
c = newChartData()
@ -173,28 +174,3 @@ func ParseDataFile(file string) ([]*ChartDataType, error) {
charts = append(charts, c)
return charts, nil
}
func LookupCurrentDir(dir string) ([]string, error) {
var tmp []string = make([]string, 0, 5)
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if f.IsDir() {
return nil
}
if ok, err := filepath.Match("*.chart", f.Name()); err != nil {
return err
} else if ok {
if path == f.Name() {
tmp = append(tmp, path)
}
}
return nil
})
return tmp, err
}

View File

@ -1,5 +1,5 @@
===
{ "Name" : "bar", "Height" : 300, "Width" : 550 }
{ "Type":"bar", "Height":300, "Width":550 }
---
aaa 10 13
bbb 15 12

View File

@ -1,7 +1,7 @@
===
{ "Name" : "line", "Height" : 300, "Width" : 550 }
{ "Type":"line", "Height":300, "Width":550 }
---
aaa 10 13 10
bbb 15 12 11
ccc 23 14 15
ddd 20 24 25
1.0 10 13 10
2.0 15 12 11
3.0 23 14 15
4.0 20 24 25

View File

@ -1,5 +1,5 @@
===
{ "Name" : "pie", "Height" : 300, "Width" : 550 }
{ "Type":"pie", "Height":300, "Width":550 }
---
aaa 10
bbb 15

28
main.go
View File

@ -1,9 +1,29 @@
package main
const start = `version: 1.0
http://localhost:8000`
import (
"flag"
"fmt"
)
var (
ChartDir string
Welcome string = `version: 1.0
http://localhost:`
)
func usage() {
fmt.Println("goplot version v1.0.1")
flag.PrintDefaults()
}
func main() {
println(start)
println(ListenAndServe(":8000").Error())
var port string
flag.StringVar(&ChartDir, "c", "./", "Chart dir")
flag.StringVar(&port, "p", "8000", "Listen port")
flag.Usage = usage
flag.Parse()
Welcome += port
println(Welcome)
println(ListenAndServe(":" + port).Error())
}

View File

@ -2,6 +2,7 @@ package main
import (
"net/http"
"path/filepath"
"strings"
"text/template"
)
@ -40,24 +41,17 @@ type ChartIf interface {
NewChart(string) string
}
var (
ChartHandlers = make(map[string]ChartIf)
ChartFiles []string
Index int
)
var ChartHandlers = make(map[string]ChartIf)
func handler(w http.ResponseWriter, r *http.Request) {
if len(ChartFiles) == 0 {
urls := strings.Split(r.URL.String(), "/")
if 2 > len(urls) {
w.Write([]byte("RouteError"))
return
}
var file string
if Index < len(ChartFiles) {
file = ChartFiles[Index]
Index++
} else {
Index = 0
file = ChartFiles[Index]
}
file := urls[1] + ".chart"
file = filepath.Join(ChartDir, file)
datas, err := ParseDataFile(file)
if err != nil {
@ -80,12 +74,8 @@ func handler(w http.ResponseWriter, r *http.Request) {
return
} else {
var ok bool
urls := strings.Split(r.URL.String(), "/")
if 2 > len(urls) {
w.Write([]byte(err.Error()))
return
}
chart, ok = ChartHandlers[urls[1]]
chart, ok = ChartHandlers[prop.Type]
if !ok {
w.Write([]byte(err.Error()))
return
@ -118,10 +108,5 @@ func ListenAndServe(addr string) error {
http.HandleFunc("/", handler)
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {})
var err error
ChartFiles, err = LookupCurrentDir(".")
if err != nil {
return err
}
return http.ListenAndServe(addr, nil)
}