diff --git a/README.md b/README.md
index 71761ce..4c2de00 100644
--- a/README.md
+++ b/README.md
@@ -224,6 +224,29 @@ konstrukt gen interlocking --color1 "#f7f1e3" --color2 "#40407a" --color3 "#33d9
+### Whitegold
+
+The pattern and default implementation is [MarcelMues](https://github.com/MarcelMue) work titled `whitegold`.
+
+
+Usage examples
+
+The default can be generated with:
+```
+konstrukt gen whitegold
+```
+
+
+
+Changing the colors can be easily done like this:
+```
+konstrukt gen whitegold --color1 "#dff9fb" --color2 "#6ab04c" --filename whitegold-au.svg
+```
+
+
+
+
+
## Guidelines
Additions to this project should follow these guidelines:
diff --git a/cmd/gen/command.go b/cmd/gen/command.go
index 7e42e69..591436e 100644
--- a/cmd/gen/command.go
+++ b/cmd/gen/command.go
@@ -17,6 +17,7 @@ import (
"github.com/marcelmue/konstrukt/cmd/gen/quadrat"
"github.com/marcelmue/konstrukt/cmd/gen/shining"
"github.com/marcelmue/konstrukt/cmd/gen/swiss16"
+ "github.com/marcelmue/konstrukt/cmd/gen/whitegold"
)
const (
@@ -169,6 +170,20 @@ func New(config Config) (*cobra.Command, error) {
}
}
+ var whitegoldCmd *cobra.Command
+ {
+ c := whitegold.Config{
+ Logger: config.Logger,
+ Stderr: config.Stderr,
+ Stdout: config.Stdout,
+ }
+
+ whitegoldCmd, err = whitegold.New(c)
+ if err != nil {
+ return nil, microerror.Mask(err)
+ }
+ }
+
f := &flag{}
r := &runner{
@@ -196,6 +211,7 @@ func New(config Config) (*cobra.Command, error) {
c.AddCommand(modernhiveCmd)
c.AddCommand(swiss16Cmd)
c.AddCommand(interlockingCmd)
+ c.AddCommand(whitegoldCmd)
return c, nil
}
diff --git a/cmd/gen/whitegold/command.go b/cmd/gen/whitegold/command.go
new file mode 100644
index 0000000..b3a9e36
--- /dev/null
+++ b/cmd/gen/whitegold/command.go
@@ -0,0 +1,53 @@
+package whitegold
+
+import (
+ "io"
+ "os"
+
+ "github.com/giantswarm/microerror"
+ "github.com/giantswarm/micrologger"
+ "github.com/spf13/cobra"
+)
+
+const (
+ name = "whitegold"
+ description = "Draws MarcelMues 'whitegold'."
+)
+
+type Config struct {
+ Logger micrologger.Logger
+ Stderr io.Writer
+ Stdout io.Writer
+}
+
+func New(config Config) (*cobra.Command, error) {
+ if config.Logger == nil {
+ return nil, microerror.Maskf(invalidConfigError, "%T.Logger must not be empty", config)
+ }
+ if config.Stderr == nil {
+ config.Stderr = os.Stderr
+ }
+ if config.Stdout == nil {
+ config.Stdout = os.Stdout
+ }
+
+ f := &flag{}
+
+ r := &runner{
+ flag: f,
+ logger: config.Logger,
+ stderr: config.Stderr,
+ stdout: config.Stdout,
+ }
+
+ c := &cobra.Command{
+ Use: name,
+ Short: description,
+ Long: description,
+ RunE: r.Run,
+ }
+
+ f.Init(c)
+
+ return c, nil
+}
diff --git a/cmd/gen/whitegold/command_test.go b/cmd/gen/whitegold/command_test.go
new file mode 100644
index 0000000..f938a1d
--- /dev/null
+++ b/cmd/gen/whitegold/command_test.go
@@ -0,0 +1,88 @@
+package whitegold
+
+import (
+ "fmt"
+ "strconv"
+ "testing"
+
+ "github.com/giantswarm/micrologger"
+)
+
+func Test_command(t *testing.T) {
+ testCases := []struct {
+ name string
+ c1 string
+ c2 string
+ filename string
+ height int
+ width int
+ }{
+ {
+ name: "case 0: default pattern",
+ filename: "whitegold",
+ },
+ {
+ name: "case 1: au color pattern",
+ filename: "whitegold-au",
+ c1: "#dff9fb",
+ c2: "#6ab04c",
+ },
+ {
+ name: "case 2: banner resize",
+ filename: "whitegold-wide",
+ width: 2000,
+ height: 400,
+ },
+ }
+
+ for i, tc := range testCases {
+ t.Run(strconv.Itoa(i), func(t *testing.T) {
+ t.Log(tc.name)
+
+ var err error
+
+ var logger micrologger.Logger
+ {
+ c := micrologger.Config{}
+
+ logger, err = micrologger.New(c)
+ if err != nil {
+ t.Fatal("expected", nil, "got", err)
+ }
+ }
+
+ c := Config{
+ Logger: logger,
+ }
+
+ testCommand, err := New(c)
+ if err != nil {
+ t.Fatal("expected", nil, "got", err)
+ }
+
+ args := []string{}
+ if tc.filename != "" {
+ args = append(args, []string{"--filename", fmt.Sprintf("../../../samples/%s.svg", tc.filename)}...)
+ }
+ if tc.c1 != "" {
+ args = append(args, []string{"--color1", tc.c1}...)
+ }
+ if tc.c2 != "" {
+ args = append(args, []string{"--color2", tc.c2}...)
+ }
+ if tc.height != 0 {
+ args = append(args, []string{"--height", strconv.Itoa(tc.height)}...)
+ }
+ if tc.width != 0 {
+ args = append(args, []string{"--width", strconv.Itoa(tc.width)}...)
+ }
+
+ testCommand.SetArgs(args)
+
+ err = testCommand.Execute()
+ if err != nil {
+ t.Fatal("expected", nil, "got", err)
+ }
+ })
+ }
+}
diff --git a/cmd/gen/whitegold/error.go b/cmd/gen/whitegold/error.go
new file mode 100644
index 0000000..f3eeb7d
--- /dev/null
+++ b/cmd/gen/whitegold/error.go
@@ -0,0 +1,21 @@
+package whitegold
+
+import "github.com/giantswarm/microerror"
+
+var invalidConfigError = µerror.Error{
+ Kind: "invalidConfigError",
+}
+
+// IsInvalidConfig asserts invalidConfigError.
+func IsInvalidConfig(err error) bool {
+ return microerror.Cause(err) == invalidConfigError
+}
+
+var invalidFlagError = µerror.Error{
+ Kind: "invalidFlagError",
+}
+
+// IsInvalidFlag asserts invalidFlagError.
+func IsInvalidFlag(err error) bool {
+ return microerror.Cause(err) == invalidFlagError
+}
diff --git a/cmd/gen/whitegold/flag.go b/cmd/gen/whitegold/flag.go
new file mode 100644
index 0000000..ecd319c
--- /dev/null
+++ b/cmd/gen/whitegold/flag.go
@@ -0,0 +1,65 @@
+package whitegold
+
+import (
+ "github.com/giantswarm/microerror"
+ "github.com/spf13/cobra"
+
+ "github.com/marcelmue/konstrukt/pkg/validate"
+)
+
+const (
+ flagFilename = "filename"
+
+ flagHeight = "height"
+ flagWidth = "width"
+
+ flagColor1 = "color1"
+ flagColor2 = "color2"
+
+ flagRandomize = "randomize"
+)
+
+type flag struct {
+ Filename string
+
+ Height int
+ Width int
+
+ Color1 string
+ Color2 string
+
+ Randomize bool
+}
+
+func (f *flag) Init(cmd *cobra.Command) {
+ cmd.Flags().StringVar(&f.Filename, flagFilename, "whitegold.svg", `Name of the output file.`)
+
+ cmd.Flags().IntVar(&f.Height, flagHeight, 500, `Height of the output file in pixels.`)
+ cmd.Flags().IntVar(&f.Width, flagWidth, 500, `Width of the output file in pixels.`)
+
+ cmd.Flags().StringVar(&f.Color1, flagColor1, "#130f40", `First color.`)
+ cmd.Flags().StringVar(&f.Color2, flagColor2, "#ffd32a", `Second color.`)
+
+ cmd.Flags().BoolVar(&f.Randomize, flagRandomize, false, "Randomize all colors in the pattern, ignore other color flags.")
+}
+
+func (f *flag) Validate() error {
+ if !validate.Color(f.Color1) {
+ validate.PrintFailure(flagColor1)
+ return microerror.Mask(invalidFlagError)
+ }
+ if !validate.Color(f.Color2) {
+ validate.PrintFailure(flagColor2)
+ return microerror.Mask(invalidFlagError)
+ }
+ if !validate.Size(f.Height) {
+ validate.PrintFailure(flagHeight)
+ return microerror.Mask(invalidFlagError)
+ }
+ if !validate.Size(f.Width) {
+ validate.PrintFailure(flagWidth)
+ return microerror.Mask(invalidFlagError)
+ }
+
+ return nil
+}
diff --git a/cmd/gen/whitegold/runner.go b/cmd/gen/whitegold/runner.go
new file mode 100644
index 0000000..afa76e9
--- /dev/null
+++ b/cmd/gen/whitegold/runner.go
@@ -0,0 +1,102 @@
+package whitegold
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "os"
+
+ svg "github.com/ajstarks/svgo"
+ "github.com/giantswarm/microerror"
+ "github.com/giantswarm/micrologger"
+ "github.com/spf13/cobra"
+
+ "github.com/marcelmue/konstrukt/pkg/color"
+ "github.com/marcelmue/konstrukt/pkg/project"
+)
+
+type runner struct {
+ flag *flag
+ logger micrologger.Logger
+ stdout io.Writer
+ stderr io.Writer
+}
+
+func (r *runner) Run(cmd *cobra.Command, args []string) error {
+ ctx := context.Background()
+
+ err := r.flag.Validate()
+ if err != nil {
+ return microerror.Mask(err)
+ }
+
+ if r.flag.Randomize {
+ r.flag.Color1 = color.Random()
+ r.flag.Color2 = color.Random()
+ fmt.Printf("Set Color1:%s Color2:%s\n", r.flag.Color1, r.flag.Color2)
+ }
+
+ err = r.run(ctx, cmd, args)
+ if err != nil {
+ return microerror.Mask(err)
+ }
+
+ return nil
+}
+
+func (r *runner) run(ctx context.Context, cmd *cobra.Command, args []string) error {
+ f, err := os.Create(r.flag.Filename)
+ if err != nil {
+ return microerror.Mask(err)
+ }
+ width, height := r.flag.Width, r.flag.Height
+ c1, c2 := r.flag.Color1, r.flag.Color2
+
+ canvas := svg.New(f)
+ canvas.Start(width, height)
+ canvas.Desc(project.PatternDesc())
+ canvas.Rect(0, 0, width, height, "fill:"+c1)
+
+ // Polygon.
+ xp := []int{25, 10, 30, 10, 25, 55}
+ yp := []int{0, 15, 45, 80, 90, 45}
+
+ // Diamond 1.
+ xd := []int{0, 11, 0}
+ yd := []int{2, -7, -22}
+
+ // Diamond 2.
+ xq := []int{0, 11, 0}
+ yq := []int{57, 48, 33}
+
+ canvas.Def()
+ canvas.Gid("unit")
+ canvas.Polygon(xp, yp)
+ canvas.Polygon(xd, yd)
+ canvas.Polygon(xq, yq)
+ canvas.Gend()
+ canvas.Gid("runit")
+ canvas.ScaleXY(-1, 1)
+ canvas.Use(0, 0, "#unit")
+ canvas.Gend()
+ canvas.Gend()
+ canvas.DefEnd()
+
+ ypositioncounter := 0
+ for y := -112; y < height+200; y += 56 {
+ for x := -200; x < width+200; x += 200 {
+ if ypositioncounter%2 == 0 {
+ canvas.Use(x, y, "#unit", "fill:"+c2)
+ canvas.Use(x, y, "#runit", "fill:"+c2)
+ }
+ if ypositioncounter%2 == 1 {
+ canvas.Use(x+100, y, "#unit", "fill:"+c2)
+ canvas.Use(x+100, y, "#runit", "fill:"+c2)
+ }
+ }
+ ypositioncounter++
+ }
+ canvas.End()
+
+ return nil
+}
diff --git a/samples/whitegold-au.svg b/samples/whitegold-au.svg
new file mode 100644
index 0000000..593b604
--- /dev/null
+++ b/samples/whitegold-au.svg
@@ -0,0 +1,170 @@
+
+
+
diff --git a/samples/whitegold-wide.svg b/samples/whitegold-wide.svg
new file mode 100644
index 0000000..1a13fd2
--- /dev/null
+++ b/samples/whitegold-wide.svg
@@ -0,0 +1,332 @@
+
+
+
diff --git a/samples/whitegold.svg b/samples/whitegold.svg
new file mode 100644
index 0000000..5000302
--- /dev/null
+++ b/samples/whitegold.svg
@@ -0,0 +1,170 @@
+
+
+