Seed, templates, web-output and SVG-output optimizations

This commit is contained in:
Aaron Fischer 2021-03-17 14:39:40 +01:00
parent a1a65165ca
commit 3d58303936
9 changed files with 152 additions and 32 deletions

View file

@ -2,49 +2,59 @@ package main
import ( import (
"f00860/kartograph-map-editor/pkg/generator" "f00860/kartograph-map-editor/pkg/generator"
"f00860/kartograph-map-editor/pkg/web"
"flag" "flag"
"fmt" "fmt"
"time"
) )
var ( var (
format string startWebserver bool
address string
port int
size int output string
world generator.World
seed string
size int
wastelands int wastelands int
mountains int mountains int
ruins int ruins int
filename string
) )
func main() { func main() {
world := generator.New(size, wastelands, mountains, ruins) if startWebserver {
web.Start(address, port)
return
}
switch format { world := generator.New(size, wastelands, mountains, ruins, seed)
switch output {
case "svg": case "svg":
fmt.Print(world.SVG()) fmt.Printf("%s", world.SVG())
case "ascii": case "ascii":
fmt.Print(world.Plot()) fmt.Printf("%s", world.Plot())
case "json": case "json":
fmt.Print(world.JSON()) fmt.Printf("%s", world.JSON())
case "pdf": default:
world.PDF(filename) fmt.Printf("Output format '%v' not supported", output)
case "web":
panic("Not implemented yet")
} }
} }
func init() { func init() {
flag.StringVar(&format, "format", "svg", "Output format (ascii, json, svg, pdf, web)") flag.BoolVar(&startWebserver, "web", false, "Spawn a webserver")
flag.StringVar(&address, "address", "0.0.0.0", "IP to bin the service to")
flag.IntVar(&port, "port", 80, "Port to bind the service to")
flag.IntVar(&size, "size", 11, "The size of the map") flag.StringVar(&output, "output", "svg", "Output format (svg, ascii, json)")
flag.StringVar(&seed, "seed", time.Now().String(), "A seed string for the map generation")
flag.IntVar(&wastelands, "wastelands", 7, "Number of wastelands") flag.IntVar(&size, "size", 11, "The map size")
flag.IntVar(&mountains, "mountains", 5, "Number of mountains") flag.IntVar(&wastelands, "wastelands", 7, "Number of wastelands to generate")
flag.IntVar(&ruins, "ruins", 6, "Number of ruins") flag.IntVar(&mountains, "mountains", 5, "Number of mountains ot generate")
flag.IntVar(&ruins, "ruins", 6, "Number of ruins to generate")
flag.StringVar(&filename, "filename", "map.pdf", "The PDF filename")
flag.Parse() flag.Parse()
} }

2
go.mod
View file

@ -1,6 +1,6 @@
module f00860/kartograph-map-editor module f00860/kartograph-map-editor
go 1.15 go 1.16
require ( require (
github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb

View file

@ -1,12 +1,7 @@
package generator package generator
import ( import ()
"github.com/jung-kurt/gofpdf"
)
func (w World) PDF(filename string) { func (w World) PDF() {
pdf := gofpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.OutputFileAndClose(filename)
} }

View file

@ -52,7 +52,7 @@ func (w World) SVG() string {
x, y := w.ToXY(pos) x, y := w.ToXY(pos)
switch tile.Territory { switch tile.Territory {
case RuinsTerritory: case RuinsTerritory:
canvas.Text(hPadding+x*gridsize+3, vPadding+(y*gridsize)+16, "R", "stroke:lightgrey;fill:lightgrey") canvas.Text(hPadding+x*gridsize+3, vPadding+(y*gridsize)+16, "R", "stroke:black;fill:black")
case MountainTerritory: case MountainTerritory:
canvas.Rect(hPadding+x*gridsize, vPadding+y*gridsize, gridsize, gridsize, "fill:white; stroke:black") canvas.Rect(hPadding+x*gridsize, vPadding+y*gridsize, gridsize, gridsize, "fill:white; stroke:black")
canvas.Circle(hPadding+x*gridsize+gridsize/2, vPadding+y*gridsize+gridsize/2, gridsize/2-8, "fill:white; stroke:black") canvas.Circle(hPadding+x*gridsize+gridsize/2, vPadding+y*gridsize+gridsize/2, gridsize/2-8, "fill:white; stroke:black")

View file

@ -1,12 +1,14 @@
package generator package generator
import ( import (
"crypto/md5"
"encoding/binary"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"math" "math"
"math/rand" "math/rand"
"time"
) )
type TerritoryType int type TerritoryType int
@ -67,6 +69,7 @@ type World struct {
Mountains int `json:"mountains"` Mountains int `json:"mountains"`
World []Tile `json:"tiles"` World []Tile `json:"tiles"`
Seed int
} }
func (w World) Plot() string { func (w World) Plot() string {
@ -92,8 +95,12 @@ func (w World) ExportToPDF(filename string) error {
return nil return nil
} }
func New(size int, numWastelands int, numMountains int, numRuins int) World { func New(size int, numWastelands int, numMountains int, numRuins int, seed string) World {
rand.Seed(time.Now().UnixNano()) // Fix seed
h := md5.New()
io.WriteString(h, seed)
var intSeed uint64 = binary.BigEndian.Uint64(h.Sum(nil))
rand.Seed(int64(intSeed))
w := World{ w := World{
Size: size, Size: size,

74
pkg/web/service.go Normal file
View file

@ -0,0 +1,74 @@
package web
import (
"embed"
"f00860/kartograph-map-editor/pkg/generator"
"html/template"
"io"
"log"
"net/http"
"strconv"
"time"
)
//go:embed templates
var templateFiles embed.FS
//go:embed static
var staticFiles embed.FS
func Start(address string, port int) {
http.Handle("/static/", http.FileServer(http.FS(staticFiles)))
http.HandleFunc("/", indexHandler)
http.HandleFunc("/map.svg", mapHandler)
addr := address + ":" + strconv.Itoa(port)
log.Printf("Server started on %v ...", addr)
err := http.ListenAndServe(addr, nil)
if err != nil {
log.Fatal(err)
}
}
func mapHandler(w http.ResponseWriter, req *http.Request) {
size, err := strconv.Atoi(req.URL.Query().Get("size"))
if err != nil {
size = 11
}
seed := req.URL.Query().Get("seed")
if seed == "" {
seed = time.Now().String()
}
wastelands, err := strconv.Atoi(req.URL.Query().Get("wastelands"))
if err != nil {
wastelands = 7
}
mountains, err := strconv.Atoi(req.URL.Query().Get("mountains"))
if err != nil {
mountains = 5
}
ruins, err := strconv.Atoi(req.URL.Query().Get("ruins"))
if err != nil {
ruins = 6
}
world := generator.New(size, wastelands, mountains, ruins, seed)
log.Printf("GET /map.svg?%v (%v)", req.URL.Query().Encode(), req.RemoteAddr)
w.Header().Set("Content-Type", "image/svg+xml")
w.Header().Set("Content-Length", strconv.Itoa(len(world.SVG())))
io.WriteString(w, world.SVG())
}
func indexHandler(w http.ResponseWriter, req *http.Request) {
log.Printf("GET / (%v)", req.RemoteAddr)
tpl, err := template.ParseFS(templateFiles, "templates/index.tpl.html")
if err != nil {
log.Fatal(err)
}
tpl.Execute(w, nil)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

10
pkg/web/static/styles.css Normal file
View file

@ -0,0 +1,10 @@
p > img {
float: right;
width: 250px;
}
.map {
margin: auto;
display: block;
width: 350px;
}

View file

@ -0,0 +1,24 @@
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Map Generator für "Der Kartograph"</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/static/styles.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<h1>Map Generator für "Der Kartograph"</h1>
<p><img src="/static/images/logo.jpg">
Wem der beigelegte Block zu eintönig wird oder schon leergespielt hat, kann sich
entweder die Mini-Erweiterung kaufen, in dem ein weiterer Block enthalten ist,
oder aber diesen Generator nutzen, um sich zufällige Maps generieren zu lassen.
Die generierten Karten entsprechen den erweiterten Regeln, können aber für etwas
mehr Spaß angepasst werden.</p>
<a href="/">Neue Map generieren</a>
<br><br>
<img src="/map.svg" class="map">
</body>
</html>