forked from OrgGo/goplot
每次刷新都实时解析路由中给出的 .chart 文件.
Signed-off-by: lion.chan <cy187lion@sina.com>
This commit is contained in:
parent
e9103b47a6
commit
15e7b02ed1
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal 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}"
|
||||
}
|
||||
]
|
||||
}
|
32
README.md
32
README.md
@ -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 的 Name,goplot 会根据该 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>
|
||||
```
|
||||
|
||||
##### 曲线图
|
||||

|
||||
## 曲线图
|
||||
|
||||
##### 柱状图
|
||||

|
||||

|
||||
|
||||
##### 饼图
|
||||

|
||||
## 柱状图
|
||||
|
||||

|
||||
|
||||
## 饼图
|
||||
|
||||

|
||||
|
42
data.go
42
data.go
@ -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
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
===
|
||||
{ "Name" : "bar", "Height" : 300, "Width" : 550 }
|
||||
{ "Type":"bar", "Height":300, "Width":550 }
|
||||
---
|
||||
aaa 10 13
|
||||
bbb 15 12
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
===
|
||||
{ "Name" : "pie", "Height" : 300, "Width" : 550 }
|
||||
{ "Type":"pie", "Height":300, "Width":550 }
|
||||
---
|
||||
aaa 10
|
||||
bbb 15
|
||||
|
28
main.go
28
main.go
@ -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())
|
||||
}
|
||||
|
35
server.go
35
server.go
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user