Skip to content
Snippets Groups Projects
Commit 8032dec4 authored by Tóth Miklós Tibor's avatar Tóth Miklós Tibor :shrug:
Browse files

use vis.js

parent 97a06951
Branches
No related tags found
No related merge requests found
...@@ -6,11 +6,6 @@ import ( ...@@ -6,11 +6,6 @@ import (
"log" "log"
) )
type GraphNode struct {
Device *Device
Children []*GraphNode
}
type QueryReturnType struct { type QueryReturnType struct {
Device *Device Device *Device
Edge struct { Edge struct {
...@@ -72,6 +67,7 @@ func GetAllDevicesAsTree(ctx context.Context) (*GraphNode, error) { ...@@ -72,6 +67,7 @@ func GetAllDevicesAsTree(ctx context.Context) (*GraphNode, error) {
node = &GraphNode{ node = &GraphNode{
Device: dev, Device: dev,
Children: nil, Children: nil,
ExtraData: make(map[string]interface{}),
} }
nodeCache[dev.Id] = node nodeCache[dev.Id] = node
} }
......
package models
func CalcPowerUsageForGraphNodes(graph *GraphNode) {
if len(graph.Children) != 0 {
for _, g := range graph.Children {
CalcPowerUsageForGraphNodes(g)
}
}
sum := 0.0
for _, g := range graph.Children {
if power, ok := g.ExtraData["power"]; ok {
if power, ok := power.(float64); ok {
sum += power
}
}
sum += g.Device.PowerConsumption
}
graph.ExtraData["power"] = sum
}
...@@ -30,3 +30,9 @@ type PluggedIn struct { ...@@ -30,3 +30,9 @@ type PluggedIn struct {
Device string `json:"_from"` Device string `json:"_from"`
PluggedInto string `json:"_to"` PluggedInto string `json:"_to"`
} }
type GraphNode struct {
Device *Device
Children []*GraphNode
ExtraData map[string]interface{}
}
package web
import (
"git.sch.bme.hu/mikewashere/power-distribution/models"
"github.com/gin-gonic/gin"
"net/http"
)
type visJS struct {
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
}
type Node struct {
Id string `json:"id"`
Value float64 `json:"value"`
Label string `json:"label"`
}
type Edge struct {
From string `json:"from"`
To string `json:"to"`
Value float64 `json:"value"`
}
func visJSFromGraph(g *models.GraphNode) *visJS {
if _, ok := g.ExtraData["power"]; !ok {
models.CalcPowerUsageForGraphNodes(g)
}
devicesMap := make(map[*models.Device]bool)
edges := make([]Edge, 0)
processNode(g, devicesMap, &edges)
nodes := make([]Node, len(devicesMap))
i := 0
for d := range devicesMap {
nodes[i].Label = d.Name
nodes[i].Value = d.PowerConsumption
nodes[i].Id = d.Id
i++
}
return &visJS{
Edges: edges,
Nodes: nodes,
}
}
func api(c *gin.Context) {
g, e := models.GetAllDevicesAsTree(c)
if e != nil {
c.Error(e)
}
c.JSON(http.StatusOK, visJSFromGraph(g))
}
func processNode(g *models.GraphNode, devices map[*models.Device]bool, edges *[]Edge) {
devices[g.Device] = true
for _, e := range g.Children {
power := e.Device.PowerConsumption
if p, ok := e.ExtraData["power"]; ok {
if p, ok := p.(float64); ok {
power += p
}
}
*edges = append(*edges, Edge{
From: g.Device.Id,
To: e.Device.Id,
Value: power,
})
processNode(e, devices, edges)
}
}
...@@ -18,4 +18,5 @@ func init() { ...@@ -18,4 +18,5 @@ func init() {
Router.GET("/", renderTemplate) Router.GET("/", renderTemplate)
Router.StaticFS("/static", http.FS(staticfs)) Router.StaticFS("/static", http.FS(staticfs))
Router.GET("/api", api)
} }
...@@ -2,6 +2,7 @@ package web ...@@ -2,6 +2,7 @@ package web
import ( import (
"embed" "embed"
"encoding/json"
"git.sch.bme.hu/mikewashere/power-distribution/models" "git.sch.bme.hu/mikewashere/power-distribution/models"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"html/template" "html/template"
...@@ -18,14 +19,22 @@ var html = template.Must(template.ParseFS(templates, "templates/*")) ...@@ -18,14 +19,22 @@ var html = template.Must(template.ParseFS(templates, "templates/*"))
func renderTemplate(c *gin.Context) { func renderTemplate(c *gin.Context) {
var graph *models.GraphNode var graph *models.GraphNode
var visjs template.JS
if c.FullPath() == "/" { if c.FullPath() == "/" {
var e error var e error
graph, e = models.GetAllDevicesAsTree(c) graph, e = models.GetAllDevicesAsTree(c)
if e != nil { if e != nil {
c.Error(e) c.Error(e)
} }
v := visJSFromGraph(graph)
vis, e := json.Marshal(v)
if e != nil {
c.Error(e)
}
visjs = template.JS(vis)
} }
c.HTML(http.StatusOK, "index.html", gin.H{ c.HTML(http.StatusOK, "index.html", gin.H{
"graph": graph, "graph": graph,
"visjs": visjs,
}) })
} }
{{ define "consumer" }} {{ define "consumer" }}
<li> <li>
<a href="#">{{.Device.Name}}</a> <a href="#">{{.Device.Name}} ({{ index .ExtraData "power" }} + {{ .Device.PowerConsumption}} W)</a>
{{ if .Children }} {{ if .Children }}
<ul> <ul>
{{ range .Children }} {{ range .Children }}
......
...@@ -3,19 +3,33 @@ ...@@ -3,19 +3,33 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Power meme</title> <title>Power meme</title>
<link rel="stylesheet" type="text/css" href="/static/tree.css"> <script type="text/javascript" src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
</head> </head>
<style> <style>
.tree { html, body {
overflow: scroll; width: 100%;
height: 100%;
padding: 0;
margin: 0;
} }
</style> </style>
<body> <body>
<div class="tree"> <script>
<ul> const data = {{ .visjs }};
{{ template "consumer" .graph }} const container = document.body;
</ul> const options = {
</div> nodes: {
shape: "dot",
scaling: {
customScalingFunction: function (min, max, total, value) {
return value/total;
},
min: 5,
max: 150
}
}
};
network = new vis.Network(container, data, options);
</script>
</body> </body>
</html> </html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Power meme</title>
<link rel="stylesheet" type="text/css" href="/static/tree.css">
</head>
<style>
.tree {
overflow: scroll;
}
</style>
<body>
<div class="tree">
<ul>
{{ template "consumer" .graph }}
</ul>
</div>
</body>
</html>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment