wardleyToGo

package module
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2023 License: MIT Imports: 12 Imported by: 0

README

WardleyToGo

Go Reference codecov

A set of primitives to "code a map". In the context of the package "a map" represents a landscape. The landscape is made of "Components". Each component knows its own location on a map. Components can collaborate, meaning that they may be linked together. Therefore a map is also a graph. The entrypoint of this API is the 'Map' structure

wtg: language

wtg is a high level language to design and render Wardley Maps implemented with this SDK.

Check the online demo (wtg playground) and the doc at https://owulveryck.github.io/wardleyToGo/

Credits: this demo is heavily inspired by GraphvizOnline. It uses:

Using the library

The wtg DSL

example:

title: sample map // title is optional
/***************
  value chain 
****************/

business - cup of tea
public - cup of tea
cup of tea - cup
cup of tea -- tea
cup of tea --- hot water
hot water - water
hot water -- kettle
kettle - power

/***************
  definitions 
****************/

// you can inline the evolution
business: |....|....|...x.|.........|

public: |....|....|....|.x...|

// or create blocks
cup of tea: {
  evolution: |....|....|..x..|........|
  color: Green // you can set colors
}
cup: {
  type: buy
  evolution: |....|....|....|....x....|
}
tea: {
  type: buy
  evolution: |....|....|....|.....x....|
}
hot water: {
  evolution: |....|....|....|....x....|
  color: Blue
}
water: {
  type: outsource
  evolution: |....|....|....|.....x....|
}

// you can set the evolution with a >
kettle: {
  type: build
  evolution: |...|...x.|..>.|.......|
}
power: {
  type: outsource
  evolution: |...|...|....x|.....>..|
}

stage1: genesis / concept
stage2: custom / emerging
stage3: product / converging
stage4: commodity / accepted

you will find tools to convert the file into SVG or dot format in the examples subdir or compiled version for various platforms in the repository

If you have Go installed, you can generate the map with

cat sample.wtg | go run main.go > wtg.svg

from the examples/wtg2svg directory

The OWM parser

The library comes with a parser to handle part of the OWM syntax.

Create a map from the owm example (see https://onlinewardleymaps.com/#h4hJOoRdO4hHSljIb9 to build one):

title Tea Shop
anchor Business [0.95, 0.63]
anchor Public [0.95, 0.78]
component Cup of Tea [0.79, 0.61] label [19, -4]
component Cup [0.73, 0.78] label [19,-4] (dataProduct)
component Tea [0.63, 0.81]
component Hot Water [0.52, 0.80]
component Water [0.38, 0.82]
component Kettle [0.43, 0.35] label [-73, 4] (build)
evolve Kettle 0.62 label [22, 9] (buy)
component Power [0.1, 0.7] label [-29, 30] (outsource)
evolve Power 0.89 label [-12, 21]
Business->Cup of Tea
Public->Cup of Tea
Cup of Tea-collaboration>Cup
Cup of Tea-collaboration>Tea
Cup of Tea-collaboration>Hot Water
Hot Water->Water
Hot Water-facilitating>Kettle 
Kettle-xAsAService>Power
build Kettle


annotation 1 [[0.43,0.49],[0.08,0.79]] Standardising power allows Kettles to evolve faster
annotation 2 [0.48, 0.85] Hot water is obvious and well known
annotations [0.60, 0.02]

note +a generic note appeared [0.16, 0.36]

style wardley
streamAlignedTeam stream aligned A [0.84, 0.18, 0.76, 0.95]
enablingTeam team B [0.9, 0.30, 0.30, 0.40]
platformTeam team C [0.18, 0.61, 0.02, 0.94]
complicatedSubsystemTeam team D [0.92, 0.73, 0.45, 0.90]

output

Developing with the library

Example

First, create a component type

type dummyComponent struct {
	id       int64
	position image.Point
}

func (d *dummyComponent) GetPosition() image.Point { return d.position }

func (d *dummyComponent) String() string { return strconv.FormatInt(d.id, 10) }

func (d *dummyComponent) ID() int64 { return d.id }

Then a collaboration structure (an edge)

type dummyCollaboration struct{ simple.Edge }

func (d *dummyCollaboration) GetType() wardleyToGo.EdgeType { return 0 }

func (d *dummyCollaboration) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	coordsF := utils.CalcCoords(d.F.(wardleyToGo.Component).GetPosition(), r)
	coordsT := utils.CalcCoords(d.T.(wardleyToGo.Component).GetPosition(), r)
	drawing.Line(dst, coordsF.X, coordsF.Y, coordsT.X, coordsT.Y, color.Gray{Y: 128}, [2]int{})
}

And finally create the map

	m := wardleyToGo.NewMap(0)
	c0 := &dummyComponent{id: 0, position: image.Pt(25, 25)}
	c1 := &dummyComponent{id: 1, position: image.Pt(50, 50)}
	c2 := &dummyComponent{id: 2, position: image.Pt(50, 75)}
	c3 := &dummyComponent{id: 3, position: image.Pt(75, 75)}
	m.AddComponent(c0)
	m.AddComponent(c1)
	m.AddComponent(c2)
	m.AddComponent(c3)
	// c0 -> c1
	// c1 -> c2
	// c2 -> c3
	// c1 -> c3
	m.SetCollaboration(newCollaboration(c0, c1))
	m.SetCollaboration(newCollaboration(c1, c2))
	m.SetCollaboration(newCollaboration(c2, c3))
	m.SetCollaboration(newCollaboration(c1, c3))

Generating image, png and so on.. (WIP)

the map fulfills the drawer.Drawer interface. If the components fulfills the interface as well, they are displayend on an image.

func main() {
	p := owm.NewParser(os.Stdin)
	m, err := p.Parse() // the map
	if err != nil {
		log.Fatal(err)
	}
	im := image.NewRGBA(image.Rect(0, 0, 1400, 1100))
	canvas := image.Rect(100, 100, 1300, 1000)
	createBackground(im, canvas)

	m.Draw(im, canvas, im, image.Point{})
	png.Encode(os.Stdout, im)
}

see the examples/pngoutput directory

png output

Documentation

Overview

Package wardleyToGo provides primitives to build an in-memory map (a plan).

In the context of the package "a map" represents a landscape.

The landscape is made of "Components". Each component knows its own location on a map.

Components can collaborate, meaning that they may be linked together. Therefore a map is also a graph.

The entrypoint of this API is the 'Map' structure

Example (Canvas)
package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"math"
	"strconv"

	"github.com/owulveryck/wardleyToGo"
	"github.com/owulveryck/wardleyToGo/internal/drawing"
	"github.com/owulveryck/wardleyToGo/internal/utils"
	"gonum.org/v1/gonum/graph"
	"gonum.org/v1/gonum/graph/path"
	"gonum.org/v1/gonum/graph/simple"
)

type dummyComponent struct {
	id       int64
	position image.Point
}

func (d *dummyComponent) GetPosition() image.Point { return d.position }

func (d *dummyComponent) String() string { return strconv.FormatInt(d.id, 10) }

func (d *dummyComponent) ID() int64 { return d.id }

func (d *dummyComponent) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	coords := utils.CalcCoords(d.position, r)
	dst.Set(coords.X, coords.Y, color.Gray{Y: 255})
}

type dummyCollaboration struct{ simple.Edge }

func (d *dummyCollaboration) GetType() wardleyToGo.EdgeType { return 0 }

func (d *dummyCollaboration) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	coordsF := utils.CalcCoords(d.F.(wardleyToGo.Component).GetPosition(), r)
	coordsT := utils.CalcCoords(d.T.(wardleyToGo.Component).GetPosition(), r)
	drawing.Line(dst, coordsF.X, coordsF.Y, coordsT.X, coordsT.Y, color.Gray{Y: 128}, [2]int{})
}

func newCollaboration(a, b wardleyToGo.Component) wardleyToGo.Collaboration {
	return &dummyCollaboration{Edge: simple.Edge{F: a, T: b}}
}

func main() {
	// Create a new map
	m := wardleyToGo.NewMap(0)
	c0 := &dummyComponent{id: 0, position: image.Pt(25, 25)}
	c1 := &dummyComponent{id: 1, position: image.Pt(50, 50)}
	c2 := &dummyComponent{id: 2, position: image.Pt(50, 75)}
	c3 := &dummyComponent{id: 3, position: image.Pt(75, 75)}
	m.AddComponent(c0)
	m.AddComponent(c1)
	m.AddComponent(c2)
	m.AddComponent(c3)
	// c0 -> c1
	// c1 -> c2
	// c2 -> c3
	// c1 -> c3
	m.SetCollaboration(newCollaboration(c0, c1))
	m.SetCollaboration(newCollaboration(c1, c2))
	m.SetCollaboration(newCollaboration(c2, c3))
	m.SetCollaboration(newCollaboration(c1, c3))

	// Creates a picture representation of the map
	const width = 80
	const height = 40

	im := image.NewGray(image.Rectangle{Max: image.Point{X: width, Y: height}})
	m.Canvas = &simpleCanvas{}

	m.Draw(im, image.Rect(5, 2, 75, 38), im, image.Point{X: 0, Y: 0})
	//m.Draw(im, im.Bounds(), im, image.Point{X: 0, Y: 0})
	// Very trivial example to draw a map on stdout
	render(im)

	//	drawMap(m)

	// Find the shortest path betwen c0 and c3
	p, _ := path.AStar(c0, c3, m, euclideanDistance)
	c0Toc3, _ := p.To(c3.ID())
	fmt.Printf("Shortest path from c0 to c3: ")
	for _, c := range c0Toc3 {
		fmt.Printf("-%v", c.ID())
	}
}

type simpleCanvas struct{}

func (s *simpleCanvas) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	draw.Draw(dst, r, image.NewUniform(color.Gray{Y: 64}), sp, draw.Src)
}

func render(im image.Image) {
	width := im.Bounds().Dx()
	pi := image.NewPaletted(im.Bounds(), []color.Color{
		color.Gray{Y: 255},
		color.Gray{Y: 160},
		color.Gray{Y: 70},
		color.Gray{Y: 35},
		color.Gray{Y: 0},
	})

	draw.FloydSteinberg.Draw(pi, im.Bounds(), im, image.Point{})
	shade := []string{" ", "░", "▒", "▓", "█"}
	for i, p := range pi.Pix {
		fmt.Print(shade[p])
		if (i+1)%width == 0 {
			fmt.Print("\n")
		}
	}
}

var euclideanDistance path.Heuristic = func(x, y graph.Node) float64 {
	xC := x.(wardleyToGo.Component).GetPosition()
	yC := y.(wardleyToGo.Component).GetPosition()
	a := xC.X - yC.X
	b := xC.Y - yC.Y
	return math.Sqrt(float64(a*a) + float64(b*b))
}
Output:

████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓ ░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒█████
█████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒░░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▓▒▒▓▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒█████
█████▒▓▒▒▓▒▒▓▒▒▓▒▓▒▒▒▒▒▒▒▒▒▓▒▒░░▓▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒█████
█████▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒░░▓▒▓▒▒▓▒▒▓▒▓▒▓▒▓▒▒▓▒▓▒▓▒▓▒▒▓▒▓▒▓▒▒▒▒▓▒▒▓█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▓░░▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒█████
█████▒▓▒▒▓▒▒▓▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▓▒░▒▒▒▓▒▒▓▒▒▒▒▒▓▒▒▒▓▒▒▒▒▓▒▒▒▓▒▒▓▒▒▒▒▓▒▒█████
█████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒ ▒▒▒▒▒▒▒▓▒▒▒▒▓▒▒▒▒▓▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▒▓▒▒▓▒▒▒▓▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒░▒░▓▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒█████
█████▒▒▒▒▒▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▓▒▒▒▓▒▒▓░▒▒░▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒█████
█████▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒░░▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒█████
█████▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒░▒▒▒▒▓▒░▒▒▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓█████
█████▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒░▓▒▒▒▒▓▒▒░▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒█████
█████▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▓░▓▒▓▒▒▒▒▒▒▒░▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▓▒▒█████
█████▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓░▓▒▒▒▒▓▒▒▓▒▒▒░░▓▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒█████
█████▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▓▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▓▒▒░▓▒▒▒▒▒▒▒▒▒▒▒▓▓░▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒█████
█████▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ ░▒░▒░▒░▒░▒░▒░░▒░ ▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒█████
█████▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒█████
█████▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒█████
█████▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒█████
█████▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓█████
█████▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒█████
█████▒▒▓▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▓▒▓▒▒▒█████
█████▒▒▒▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▒▓▒█████
█████▒▒▓▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▒▒▒▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▓▒▒▓▒▒▓▒▒▓▒▒▓▒▒▒▒▒▓▒▒▓▒▒▒▒█████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
Shortest path from c0 to c3: -0-1-3

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Annotation

type Annotation struct {
	Identifier int
	Placements []image.Point
	Label      string
}

An annotation is a set of placements of a certain label

func NewAnnotation

func NewAnnotation(identifier int) *Annotation

func (*Annotation) MarshalSVG added in v0.3.3

func (a *Annotation) MarshalSVG(e *xml.Encoder, canvas image.Rectangle) error

func (*Annotation) String

func (a *Annotation) String() string

type Area

type Area interface {
	// GetArea should be expressed wrt a 100x100 map
	GetArea() image.Rectangle
	graph.Node
}

An area is anything that covers a rectangle area on a map

type Chainer added in v0.8.1

type Chainer interface {
	// GetAbsoluteVisibility returns the visibility of the component as seen from the anchor
	GetAbsoluteVisibility() int
}

Chainer is a component that is part of a value chain

type Collaboration

type Collaboration interface {
	graph.Edge
	GetType() EdgeType
}

A Collaboration is an edge between two components with a certain type

type Component

type Component interface {
	// GetPosition of the element wrt a 100x100 map
	GetPosition() image.Point
	graph.Node
}

A Component is a node of a graph that have coordinates. A Component can represent iself on a 100x100 map

type ComponentType

type ComponentType uint8

a ComponentType

type EdgeType

type EdgeType uint8

The EdgeType

type Map

type Map struct {
	Title string
	// Canvas is the function that will draw the initial map
	// allowing the placement of the axis, legend and so on
	Canvas               draw.Drawer
	Annotations          []*Annotation
	AnnotationsPlacement image.Point

	*simple.DirectedGraph
	// contains filtered or unexported fields
}

a Map is a directed graph whose components knows their own position wrt to an anchor. The anchor is the point A of a rectangle as defined by

A := image.Point{}
image.Rectangle{A, Pt(100, 100)}

func NewMap

func NewMap(id int64) *Map

NewMap with initial area of 100x100

func (*Map) AddComponent

func (m *Map) AddComponent(e Component) error

AddComponent add e to the graph. It returns an error if e is out-of-bounds, meaning its coordinates are less than 0 or more that 100

func (*Map) Draw

func (m *Map) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point)

Draw aligns r.Min in dst with sp in src and then replaces the rectangle r in dst with the result of drawing src on dst. If the Components and Collaboration elemts of the maps are draw.Drawer, their methods are called accordingly

func (*Map) GetArea

func (m *Map) GetArea() image.Rectangle

func (*Map) GetPosition

func (m *Map) GetPosition() image.Point

GetPosition fulfills the componnts.Component interface. Therefore a map can be a component of another map. This allows doing submaping. The position is the center of the area of the map

func (*Map) ID

func (m *Map) ID() int64

a Map fulfills the graph.Node interface; thererfore if can be part of a graph of maps

func (*Map) SetCollaboration

func (m *Map) SetCollaboration(e Collaboration) error

func (*Map) String

func (m *Map) String() string
Example
package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"strconv"

	"github.com/owulveryck/wardleyToGo"
	"github.com/owulveryck/wardleyToGo/internal/drawing"
	"github.com/owulveryck/wardleyToGo/internal/utils"
	"gonum.org/v1/gonum/graph/simple"
)

type dummyComponent struct {
	id       int64
	position image.Point
}

func (d *dummyComponent) GetPosition() image.Point { return d.position }

func (d *dummyComponent) String() string { return strconv.FormatInt(d.id, 10) }

func (d *dummyComponent) ID() int64 { return d.id }

func (d *dummyComponent) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	coords := utils.CalcCoords(d.position, r)
	dst.Set(coords.X, coords.Y, color.Gray{Y: 255})
}

type dummyCollaboration struct{ simple.Edge }

func (d *dummyCollaboration) GetType() wardleyToGo.EdgeType { return 0 }

func (d *dummyCollaboration) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
	coordsF := utils.CalcCoords(d.F.(wardleyToGo.Component).GetPosition(), r)
	coordsT := utils.CalcCoords(d.T.(wardleyToGo.Component).GetPosition(), r)
	drawing.Line(dst, coordsF.X, coordsF.Y, coordsT.X, coordsT.Y, color.Gray{Y: 128}, [2]int{})
}

func newCollaboration(a, b wardleyToGo.Component) wardleyToGo.Collaboration {
	return &dummyCollaboration{Edge: simple.Edge{F: a, T: b}}
}

func main() {
	// Create a new map
	m := wardleyToGo.NewMap(0)
	c0 := &dummyComponent{id: 0, position: image.Pt(25, 25)}
	c1 := &dummyComponent{id: 1, position: image.Pt(50, 50)}
	c2 := &dummyComponent{id: 2, position: image.Pt(50, 75)}
	c3 := &dummyComponent{id: 3, position: image.Pt(75, 75)}
	m.AddComponent(c0)
	m.AddComponent(c1)
	m.AddComponent(c2)
	m.AddComponent(c3)
	// c0 -> c1
	// c1 -> c2
	// c2 -> c3
	// c1 -> c3
	m.SetCollaboration(newCollaboration(c0, c1))
	m.SetCollaboration(newCollaboration(c1, c2))
	m.SetCollaboration(newCollaboration(c2, c3))
	m.SetCollaboration(newCollaboration(c1, c3))
	fmt.Println(m)
}
Output:

Directories

Path Synopsis
dot
svg
examples
internal
svg
parser
owm
wtg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL