From 88f0f7cdb48e66223e04a2203cae6443f06e1a07 Mon Sep 17 00:00:00 2001 From: lempiy Date: Sat, 13 Jul 2019 16:05:29 +0300 Subject: [PATCH] Finish as lib --- README.md | 157 ++++++++++++++++++++++++++++++++++ ascii/bitmask.go | 2 +- ascii/canvas.go | 9 +- ascii/corner.go | 2 +- example.txt | 46 ++++++++++ main.go | 216 +---------------------------------------------- 6 files changed, 213 insertions(+), 219 deletions(-) create mode 100644 README.md create mode 100644 example.txt diff --git a/README.md b/README.md new file mode 100644 index 0000000..b67c267 --- /dev/null +++ b/README.md @@ -0,0 +1,157 @@ +## ↬ dGraph ↫ + +#### Draw direct graphs with ascii symbols using Golang and more... + +##### Usage + +```go +package main + +import ( + "encoding/json" + "log" + "fmt" + "github.com/lempiy/dgraph" + "github.com/lempiy/dgraph/core" +) + +const data = `[ +{ + "id": "Client", + "next": ["Route53"] +}, +{ + "id": "Route53", + "next": ["ELB", "CloudFront"] +}, +{ + "id": "CloudFront", + "next": ["S3"] +}, +{ + "id": "S3", + "next": [] +}, +{ + "id": "ELB", + "next": ["WebServer1", "WebServer2", "WebServer3", "WebServer4"] +}, +{ + "id": "WebServer1", + "next": ["LB1"] +}, +{ + "id": "WebServer2", + "next": ["LB1"] +}, +{ + "id": "WebServer3", + "next": ["LB2"] +}, +{ + "id": "WebServer4", + "next": ["LB2"] +}, +{ + "id": "LB1", + "next": ["AppServer1", "AppServer2"] +}, +{ + "id": "LB2", + "next": ["AppServer3", "AppServer4"] +}, +{ + "id": "AppServer1", + "next": ["DBMaster", "DBReplica1"] +}, +{ + "id": "AppServer2", + "next": ["DBMaster", "DBReplica1"] +}, +{ + "id": "AppServer3", + "next": ["DBMaster", "DBReplica2"] +}, +{ + "id": "AppServer4", + "next": ["DBMaster", "DBReplica2"] +}, +{ + "id": "DBReplica1", + "next": ["DBMaster"] +}, +{ + "id": "DBReplica2", + "next": ["DBMaster"] +}, +{ + "id": "DBMaster", + "next": [] +} +]` + +func main() { + var list []core.NodeInput + err := json.Unmarshal([]byte(data), &list) + if err != nil { + log.Fatal(err) + return + } + canvas, err := dgraph.DrawGraph(list) + if err != nil { + log.Fatal(err) + return + } + fmt.Printf("%s\n", canvas) +} +``` +**Output**: +``` +┌─────────┐ ┌─────────┐ ┌─────┐ ┌─────────────┐ ┌─────┐ ┌─────────────┐ ┌───────────┐ +│ Client ├───┤ Route53 ├───────┤ ELB ├───────┤ WebServer1 ├───┤ LB1 ├───┤ AppServer1 ├─────────────────────┤ DBMaster │ +└─────────┘ └────┬────┘ └──┬──┘ └─────────────┘ └──┬──┘ └──────┬──────┘ └─────┬─────┘ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ + │ ├──────────┤ WebServer2 ├──────┤ └──────────┤ DBReplica1 ├─────────┤ + │ │ └─────────────┘ │ └──────┬──────┘ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ ┌─────────────┐ │ │ + │ │ └──────┤ AppServer2 ├──────────┼────────────────┤ + │ │ └──────┬──────┘ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ └─────────────────┘ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ ┌─────────────┐ ┌─────┐ ┌─────────────┐ │ + │ ├──────────┤ WebServer3 ├───┤ LB2 ├───┤ AppServer3 ├───────────────────────────┤ + │ │ └─────────────┘ └──┬──┘ └──────┬──────┘ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ + │ └──────────┤ WebServer4 ├──────┤ └──────────┤ DBReplica2 ├─────────┤ + │ └─────────────┘ │ └──────┬──────┘ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ┌─────────────┐ ┌─────┐ │ ┌─────────────┐ │ │ + └────────┤ CloudFront ├───────┤ S3 │ └──────┤ AppServer4 ├──────────┼────────────────┘ + └─────────────┘ └─────┘ └──────┬──────┘ │ + │ │ + │ │ + │ │ + │ │ + └─────────────────┘ + + +``` +If you need to render your graph in other format. You can use `core` package to get low level `core.Matrix` struct. diff --git a/ascii/bitmask.go b/ascii/bitmask.go index 8d2039e..9ddadc4 100644 --- a/ascii/bitmask.go +++ b/ascii/bitmask.go @@ -15,7 +15,7 @@ const ( EndMarker ) -var AsciiBitmask = map[uint16]rune{ +var Bitmask = map[uint16]rune{ RightVector: '─', LeftVector: '─', HorizontalBorder: '─', diff --git a/ascii/canvas.go b/ascii/canvas.go index 3d5ce88..3f77cc9 100644 --- a/ascii/canvas.go +++ b/ascii/canvas.go @@ -37,7 +37,7 @@ func (c *Canvas) drawPixel(x, y int, flag uint16) (err error) { var newPixel Pixel switch { case pixel == nil: - newPixel.Rune = AsciiBitmask[flag] + newPixel.Rune = Bitmask[flag] newPixel.Flag = flag newPixel.InitialFlag = flag case pixel.Flag == 0: @@ -45,13 +45,12 @@ func (c *Canvas) drawPixel(x, y int, flag uint16) (err error) { resolve(flag), string([]rune{pixel.Rune}), x, y, c) return default: - newPixel.Rune = AsciiBitmask[flag|pixel.InitialFlag] + newPixel.Rune = Bitmask[flag|pixel.InitialFlag] newPixel.Flag = flag | pixel.InitialFlag newPixel.InitialFlag = pixel.InitialFlag - if AsciiBitmask[flag|pixel.InitialFlag] == 0 { + if Bitmask[flag|pixel.InitialFlag] == 0 { err = fmt.Errorf("unexpected symbol intersection new `%s` and old `%s`\n%s\n", resolve(flag), resolve(pixel.Flag), c) - fmt.Println(flag, pixel.Flag, x, y, "---", flag|pixel.Flag) return } } @@ -74,5 +73,5 @@ func (c *Canvas) String() (acc string) { } func resolve(flag uint16) string { - return string([]rune{AsciiBitmask[flag]}) + return string([]rune{Bitmask[flag]}) } diff --git a/ascii/corner.go b/ascii/corner.go index 1f4a6c8..be44365 100644 --- a/ascii/corner.go +++ b/ascii/corner.go @@ -15,7 +15,7 @@ func NewCorner(x, y int, orientation core.AnchorOrientation) *Corner { x: x, y: y, orientation: orientation, - rune: AsciiBitmask[getFlagFromOrientation(orientation)], + rune: Bitmask[getFlagFromOrientation(orientation)], flag: getFlagFromOrientation(orientation), } } diff --git a/example.txt b/example.txt new file mode 100644 index 0000000..de1dc7d --- /dev/null +++ b/example.txt @@ -0,0 +1,46 @@ +┌─────────┐ ┌─────────┐ ┌─────┐ ┌─────────────┐ ┌─────┐ ┌─────────────┐ ┌───────────┐ +│ Client ├───┤ Route53 ├───────┤ ELB ├───────┤ WebServer1 ├───┤ LB1 ├───┤ AppServer1 ├─────────────────────┤ DBMaster │ +└─────────┘ └────┬────┘ └──┬──┘ └─────────────┘ └──┬──┘ └──────┬──────┘ └─────┬─────┘ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ + │ ├──────────┤ WebServer2 ├──────┤ └──────────┤ DBReplica1 ├─────────┤ + │ │ └─────────────┘ │ └──────┬──────┘ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ ┌─────────────┐ │ │ + │ │ └──────┤ AppServer2 ├──────────┼────────────────┤ + │ │ └──────┬──────┘ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ └─────────────────┘ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ ┌─────────────┐ ┌─────┐ ┌─────────────┐ │ + │ ├──────────┤ WebServer3 ├───┤ LB2 ├───┤ AppServer3 ├───────────────────────────┤ + │ │ └─────────────┘ └──┬──┘ └──────┬──────┘ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ + │ └──────────┤ WebServer4 ├──────┤ └──────────┤ DBReplica2 ├─────────┤ + │ └─────────────┘ │ └──────┬──────┘ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ┌─────────────┐ ┌─────┐ │ ┌─────────────┐ │ │ + └────────┤ CloudFront ├───────┤ S3 │ └──────┤ AppServer4 ├──────────┼────────────────┘ + └─────────────┘ └─────┘ └──────┬──────┘ │ + │ │ + │ │ + │ │ + │ │ + └─────────────────┘ + + diff --git a/main.go b/main.go index f2291b3..17749ea 100644 --- a/main.go +++ b/main.go @@ -1,230 +1,22 @@ -package main +package dgraph import ( - "encoding/json" - "fmt" "github.com/lempiy/dgraph/ascii" "github.com/lempiy/dgraph/core" ) -//var list = []core.NodeInput{ -// { -// Id: "A", -// Next: []string{"B"}, -// }, -// { -// Id: "B", -// Next: []string{"AWS", "D", "S"}, -// }, -// { -// Id: "D", -// Next: []string{"E"}, -// }, -// { -// Id: "AWS", -// Next: []string{"F"}, -// }, -// { -// Id: "S", -// Next: []string{"DEL"}, -// }, -// { -// Id: "E", -// Next: []string{"DEL"}, -// }, -// { -// Id: "F", -// Next: []string{"DEL"}, -// }, -// { -// Id: "DEL", -// Next: []string{}, -// }, -//} - -//const data = `[ -// { -// "id": "1", -// "next": ["2"] -// }, -// { -// "id": "2", -// "next": ["3", "4"] -// }, -// { -// "id": "3", -// "next": ["5"] -// }, -// { -// "id": "6", -// "next": [] -// }, -// { -// "id": "7", -// "next": ["4"] -// }, -// { -// "id": "4", -// "next": ["8"] -// }, -// { -// "id": "8", -// "next": ["9"] -// }, -// { -// "id": "10", -// "next": ["11"] -// }, -// { -// "id": "11", -// "next": ["12", "13"] -// }, -// { -// "id": "12", -// "next": ["14"] -// }, -// { -// "id": "14", -// "next": ["15", "16"] -// }, -// { -// "id": "15", -// "next": ["17", "12"] -// }, -// { -// "id": "16", -// "next": ["17"] -// }, -// { -// "id": "17", -// "next": [] -// }, -// { -// "id": "13", -// "next": [] -// }, -// { -// "id": "9", -// "next": ["18"] -// }, -// { -// "id": "5", -// "next": ["19"] -// }, -// { -// "id": "19", -// "next": ["20"] -// }, -// { -// "id": "18", -// "next": ["20"] -// }, -// { -// "id": "20", -// "next": ["21", "6"] -// }, -// { -// "id": "21", -// "next": ["21"] -// } -//]` - -const data = `[ -{ - "id": "Client", - "next": ["Route53"] -}, -{ - "id": "Route53", - "next": ["ELB", "CloudFront"] -}, -{ - "id": "CloudFront", - "next": ["S3"] -}, -{ - "id": "S3", - "next": [] -}, -{ - "id": "ELB", - "next": ["WebServer1", "WebServer2", "WebServer3", "WebServer4"] -}, -{ - "id": "WebServer1", - "next": ["LB1"] -}, -{ - "id": "WebServer2", - "next": ["LB1"] -}, -{ - "id": "WebServer3", - "next": ["LB2"] -}, -{ - "id": "WebServer4", - "next": ["LB2"] -}, -{ - "id": "LB1", - "next": ["AppServer1", "AppServer2"] -}, -{ - "id": "LB2", - "next": ["AppServer3", "AppServer4"] -}, -{ - "id": "AppServer1", - "next": ["DBMaster", "DBReplica1"] -}, -{ - "id": "AppServer2", - "next": ["DBMaster", "DBReplica1"] -}, -{ - "id": "AppServer3", - "next": ["DBMaster", "DBReplica2"] -}, -{ - "id": "AppServer4", - "next": ["DBMaster", "DBReplica2"] -}, -{ - "id": "DBReplica1", - "next": ["DBMaster"] -}, -{ - "id": "DBReplica2", - "next": ["DBMaster"] -}, -{ - "id": "DBMaster", - "next": [] -} -]` - -func main() { - var list []core.NodeInput - err := json.Unmarshal([]byte(data), &list) - if err != nil { - fmt.Println(err) - return - } +func DrawGraph(list []core.NodeInput) (canvas *ascii.Canvas, err error) { g, err := core.NewGraph(list) if err != nil { - fmt.Println(err) return } mtx, err := g.Traverse() if err != nil { - fmt.Println(err) return } - c, err := ascii.DrawAsciiMatrix(mtx) + canvas, err = ascii.DrawAsciiMatrix(mtx) if err != nil { - fmt.Println(err) return } - fmt.Printf("%s\n", c) + return }