Skip to content

Instantly share code, notes, and snippets.

@owulveryck
Last active November 30, 2022 06:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save owulveryck/3c48bd15d1bbc146e5d70ff8e5f5c39e to your computer and use it in GitHub Desktop.
Save owulveryck/3c48bd15d1bbc146e5d70ff8e5f5c39e to your computer and use it in GitHub Desktop.
Article Wardley sources
// Stages of evolution
package main
import (
"image/color"
"log"
"math"
"os"
"golang.org/x/image/font/opentype"
"gonum.org/v1/plot"
"gonum.org/v1/plot/font"
"gonum.org/v1/plot/plotter"
)
func main() {
ttf, err := os.ReadFile("CenturyGothic.ttf")
if err != nil {
panic(err)
}
fontTTF, err := opentype.Parse(ttf)
if err != nil {
log.Fatal(err)
}
centuryGothic := font.Font{Typeface: "Century Gothic"}
font.DefaultCache.Add([]font.Face{
{
Font: centuryGothic,
Face: fontTTF,
},
})
plot.DefaultFont = centuryGothic
sigmoid := func(x float64) float64 {
return (1.0 / (1.0 + 0.2*math.Exp(-x)))
}
line := plotter.NewFunction(sigmoid)
line.Width = 4
line.Samples = 5000
line.Color = color.RGBA{R: 47, G: 175, B: 200, A: 255}
p := plot.New()
// p.Add(line2)
p.Y.Max = 1.1
p.Y.Min = 0
p.X.Max = 5
p.X.Min = -5
steps := []stage{
{name: "", evolution: 0},
{name: "Genesis", evolution: 20, color: color.RGBA{R: 43, G: 162, B: 188, A: 255}},
{name: "Custom Built", evolution: 40, color: color.RGBA{R: 100, G: 194, B: 211, A: 255}},
{name: "Product + Rental", evolution: 70, color: color.RGBA{R: 135, G: 208, B: 221, A: 255}},
{name: "Commodity", evolution: 100, color: color.RGBA{R: 219, G: 241, B: 245, A: 255}},
}
for i, s := range steps {
if i == 0 {
continue
}
var x0, x1, y0, y1 float64
x0 = (p.X.Max-p.X.Min)*steps[i-1].evolution/100 + p.X.Min - (p.X.Max-p.X.Min)*0.03
x1 = (p.X.Max-p.X.Min)*steps[i].evolution/100 + p.X.Min + (p.X.Max-p.X.Min)*0.03
y0 = sigmoid(x0) - 0.03*(p.Y.Max+p.Y.Min)
y1 = sigmoid(x1) + 0.03*(p.Y.Max+p.Y.Min)
stage, err := plotter.NewLine(plotter.XYs{
{X: x0, Y: y0}, {X: x0, Y: y1}, {X: x1, Y: y1}, {X: x1, Y: y0}, {X: x0, Y: y0},
})
if err != nil {
log.Panic(err)
}
stage.FillColor = s.color
stage.Color = s.color
p.Add(stage)
p.Legend.Add(s.name, stage)
}
for _, s := range steps {
x := (p.X.Max-p.X.Min)*s.evolution/100 + p.X.Min
stage, err := plotter.NewLine(plotter.XYs{
{X: x, Y: p.Y.Min},
{X: x, Y: p.Y.Max},
})
if err != nil {
log.Panic(err)
}
if s.evolution != 100 {
p.Add(stage)
}
}
p.X.Label.Text = "Certitude"
p.X.Label.TextStyle.Color = color.RGBA{R: 33, G: 44, B: 93, A: 255}
p.X.Tick.Marker = &ticker{}
p.Y.Tick.Marker = &ticker{}
p.Y.Label.TextStyle.Color = color.RGBA{R: 33, G: 44, B: 93, A: 255}
p.Y.Label.Text = "Présence"
p.Title.Text = "Activités"
p.Add(line)
w, err := p.WriterTo(600, 400, "png")
if err != nil {
log.Panic(err)
}
_, err = w.WriteTo(os.Stdout)
if err != nil {
log.Panic(err)
}
}
type ticker struct{}
// Ticks returns Ticks in a specified range
func (ticker *ticker) Ticks(min float64, max float64) []plot.Tick {
return []plot.Tick{}
}
type stage struct {
name string
evolution float64
color color.Color
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
title Salon de thé
anchor Business [0.95, 0.63]
anchor Public [0.95, 0.78]
component Tasse de thé [0.79, 0.61] label [19, -4]
component Tasse [0.73, 0.78]
component Thé [0.63, 0.81]
component Eau Chaude [0.52, 0.80]
component Eau [0.38, 0.82]
component Bouilloire [0.38, 0.65] label [-66, -33]
component Power [0.1, 0.7] label [-27, 20]
Business->Tasse de thé
Public->Tasse de thé
Tasse de thé->Tasse
Tasse de thé->Thé
Tasse de thé->Eau Chaude
Eau Chaude->Eau
Eau Chaude->Bouilloire
Bouilloire->Power
Display the source blob
Display the rendered blob
Raw
<svg width="100%" height="100%" viewBox="0 0 1200 700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet">
<style><![CDATA[
.evolutionEdge {
stroke-dasharray: 7;
stroke-dashoffset: 7;
animation: dash 3s linear forwards infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 100;
}
to {
stroke-dashoffset: 0;
}
}]]></style>
<rect x="0" y="0" width="1200" height="700" fill="rgb(236,237,243)" fill-opacity="0.0"></rect>
<defs>
<linearGradient id="wardleyGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="rgb(236,237,243)"></stop>
<stop offset="30%" stop-color="rgb(255,255,255)"></stop>
<stop offset="70%" stop-color="rgb(255,255,255)"></stop>
<stop offset="100%" stop-color="rgb(236,237,243)"></stop>
</linearGradient>
<marker id="arrow" refX="15" refY="0" markerWidth="12" markerHeight="12" viewBox="0 -5 10 10">
<path d="M0,-5L10,0L0,5" fill="rgb(255,0,0)"></path>
</marker>
<marker id="graphArrow" refX="9" refY="0" markerWidth="12" markerHeight="12" viewBox="0 -5 10 10">
<path d="M0,-5L10,0L0,5" fill="rgb(0,0,0)"></path>
</marker>
</defs>
<rect x="30" y="50" width="1120" height="600" style="fill:url(#wardleyGradient)"></rect>
<g transform=" translate(30,650) rotate(270)">
<line x1="0" y1="0" x2="600" y2="0" stroke-width="1" marker-end="url(#graphArrow)" stroke="rgb(19,36,84)" stroke-opacity="1.0"></line>
<line x1="0" y1="194" x2="600" y2="194" stroke-width="1" stroke-dasharray="2 2" stroke="rgb(19,36,84)" stroke-opacity="1.0"></line>
<line x1="0" y1="448" x2="600" y2="448" stroke-width="1" stroke-dasharray="2 2" stroke="rgb(19,36,84)" stroke-opacity="1.0"></line>
<line x1="0" y1="784" x2="600" y2="784" stroke-width="1" stroke-dasharray="2 2" stroke="rgb(19,36,84)" stroke-opacity="1.0"></line>
<text x="5" y="-10" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" text-anchor="start">Invisible</text>
<text x="595" y="-10" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" text-anchor="end">Visible</text>
<text x="300" y="-10" fill="rgb(19,36,84)" fill-opacity="1.0" font-weight="bold" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" text-anchor="middle">Value Chain</text>
</g>
<line x1="30" y1="650" x2="1150" y2="650" marker-end="url(#graphArrow)" stroke="rgb(19,36,84)" stroke-opacity="1.0"></line>
<text x="37" y="65" fill="rgb(19,36,84)" fill-opacity="1.0" font-weight="bold" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" font-size="11px" text-anchor="start">Uncharted</text>
<text x="1145" y="65" fill="rgb(19,36,84)" fill-opacity="1.0" font-weight="bold" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" font-size="11px" text-anchor="end">Industrialised</text>
<text x="30" y="665" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Phase I</text>
<text x="224" y="665" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Phase II</text>
<text x="478" y="665" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Phase III</text>
<text x="814" y="665" fill="rgb(19,36,84)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Phase IV</text>
<text x="1150" y="665" fill="rgb(19,36,84)" fill-opacity="1.0" font-weight="bold" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" text-anchor="end">Evolution</text>
<text x="600" y="20" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" text-anchor="middle">Salon de thé</text>
<g id="layer_0">
<g id="element_0">
<g transform=" translate(735,80)">
<text x="0" y="0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" font-size="14px" text-anchor="middle">Business</text>
</g>
</g>
<g id="element_1">
<g transform=" translate(903,80)">
<text x="0" y="0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif" font-size="14px" text-anchor="middle">Public</text>
</g>
</g>
</g>
<g id="layer_5">
<g id="edge_2_3">
<line x1="713" y1="176" x2="903" y2="212" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_2_5">
<line x1="713" y1="176" x2="926" y2="338" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_5_6">
<line x1="926" y1="338" x2="948" y2="422" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_5_7">
<line x1="926" y1="338" x2="758" y2="422" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_0_2">
<line x1="735" y1="80" x2="713" y2="176" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_7_8">
<line x1="758" y1="422" x2="814" y2="590" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_2_4">
<line x1="713" y1="176" x2="937" y2="272" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
<g id="edge_1_2">
<line x1="903" y1="80" x2="713" y2="176" stroke-width="1" stroke="rgb(128,128,128)" stroke-opacity="1.0"></line>
</g>
</g>
<g id="layer_10">
<g id="element_3">
<g transform=" translate(903,212)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="10" y="10" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Tasse</text>
</g>
</g>
<g id="element_5">
<g transform=" translate(926,338)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="10" y="10" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Eau Chaude</text>
</g>
</g>
<g id="element_8">
<g transform=" translate(814,590)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="-27" y="20" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Power</text>
</g>
</g>
<g id="element_2">
<g transform=" translate(713,176)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="19" y="-4" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Tasse de thé</text>
</g>
</g>
<g id="element_4">
<g transform=" translate(937,272)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="10" y="10" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Thé</text>
</g>
</g>
<g id="element_6">
<g transform=" translate(948,422)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="10" y="10" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Eau</text>
</g>
</g>
<g id="element_7">
<g transform=" translate(758,422)">
<circle cx="0" cy="0" r="5" fill="rgb(255,255,255)" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-opacity="1.0" stroke-width="1"></circle>
<text x="-66" y="-33" fill="rgb(0,0,0)" fill-opacity="1.0" font-family="Century Gothic,CenturyGothic,AppleGothic,sans-serif">Bouilloire</text>
</g>
</g>
</g>
</svg>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
title Salon de thé
anchor Business [0.95, 0.06]
anchor Public [0.95, 0.14]
component Tasse de thé [0.78, 0.09] label [19, -4]
component Tasse [0.73, 0.12] label [6, 30]
component Thé [0.58, 0.05]
component Eau Chaude [0.44, 0.10]
component Eau [0.38, 0.14] label [-22, 23]
component Bouilloire [0.30, 0.10] label [-66, -33]
component Power [0.12, 0.10] label [-27, 20]
Business->Tasse de thé
Public->Tasse de thé
Tasse de thé->Tasse
Tasse de thé->Thé
Tasse de thé->Eau Chaude
Eau Chaude->Eau
Eau Chaude->Bouilloire
Bouilloire->Power
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment