diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cf1a6b6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.16.2-alpine AS builder +RUN apk update +WORKDIR /app +COPY . /app +RUN GOOS=linux go build -o kartograph cmd/kartograph-map-generator/main.go + +FROM alpine:latest +RUN apk update +WORKDIR /app +COPY --from=builder /app/kartograph /app/ +EXPOSE 80 +ENTRYPOINT ["/app/kartograph"] diff --git a/README.mkd b/README.mkd new file mode 100644 index 0000000..da8ab9e --- /dev/null +++ b/README.mkd @@ -0,0 +1,34 @@ +# Der Kartograph Map Generator + +Generate your own maps for "Der Kartograph" easily. + +## Build + +You need to build the source first. The simplest way is to use the +provided Dockerfile, which will build the software and create a +convenient image (This is a multi stage Dockerfile, so the resulting +image is a small Alpine Linux image with ust the map generator binary.) + + $ docker build -t kartograph . + +## Run + +See all available options: + + $ docker run -it kartograph -help + +Spawn a webserver: + + $ docker run -it kartograph -web + +Generate a map with the seed "hey jim" and output it as a SVG image: + + $ docker run -it kartograph -output=svg -seed='hey jim' > map.svg + +You want an epic game? Lets generate a big map with a lot of wasteland +and ruins: + + $ docker run -it kartograph -seed=aaron \ + -size=20 -wastelands=100 -ruins=10 \ + -output=svg > map.svg + diff --git a/cmd/kartograph-map-generator/main.go b/cmd/kartograph-map-generator/main.go index 9d0379a..ad26e75 100644 --- a/cmd/kartograph-map-generator/main.go +++ b/cmd/kartograph-map-generator/main.go @@ -45,7 +45,7 @@ func main() { func init() { flag.BoolVar(&startWebserver, "web", false, "Spawn a webserver") - flag.StringVar(&address, "address", "0.0.0.0", "IP to bin the service to") + flag.StringVar(&address, "address", "0.0.0.0", "IP to bind the service to") flag.IntVar(&port, "port", 80, "Port to bind the service to") flag.StringVar(&output, "output", "svg", "Output format (svg, ascii, json)") diff --git a/go.mod b/go.mod index 5579bf4..70a6312 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,4 @@ go 1.16 require ( github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb - github.com/jung-kurt/gofpdf v1.16.2 ) diff --git a/pkg/generator/pdf.go b/pkg/generator/pdf.go deleted file mode 100644 index e65fc60..0000000 --- a/pkg/generator/pdf.go +++ /dev/null @@ -1,7 +0,0 @@ -package generator - -import () - -func (w World) PDF() { - -} diff --git a/pkg/generator/world.go b/pkg/generator/world.go index de7ecca..2ca6e47 100644 --- a/pkg/generator/world.go +++ b/pkg/generator/world.go @@ -9,6 +9,7 @@ import ( "io" "math" "math/rand" + "time" ) type TerritoryType int @@ -69,7 +70,7 @@ type World struct { Mountains int `json:"mountains"` World []Tile `json:"tiles"` - Seed int + Seed string } func (w World) Plot() string { @@ -90,23 +91,15 @@ func (w World) JSON() string { return string(output) } -func (w World) ExportToPDF(filename string) error { - // TODO: Draw the PDF - return nil -} - func New(size int, numWastelands int, numMountains int, numRuins int, seed string) World { - // Fix seed - h := md5.New() - io.WriteString(h, seed) - var intSeed uint64 = binary.BigEndian.Uint64(h.Sum(nil)) - rand.Seed(int64(intSeed)) + InitSeed(seed) w := World{ Size: size, Wastelands: numWastelands, Mountains: numMountains, Ruins: numRuins, + Seed: seed, } // All empty for start @@ -174,6 +167,24 @@ func New(size int, numWastelands int, numMountains int, numRuins int, seed strin return w } +func InitSeed(seed string) { + h := md5.New() + io.WriteString(h, seed) + var intSeed uint64 = binary.BigEndian.Uint64(h.Sum(nil)) + rand.Seed(int64(intSeed)) +} + +func RandomSeed() string { + InitSeed(time.Now().String()) + chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + var seed []byte + for i := 0; i < 10; i++ { + seed = append(seed, chars[roll(25)]) + } + + return string(seed) +} + func (w World) neighbour(direction int, pos int) (int, error) { switch direction { case UpDirection: diff --git a/pkg/web/service.go b/pkg/web/service.go index 2e1a75d..0faebaf 100644 --- a/pkg/web/service.go +++ b/pkg/web/service.go @@ -41,15 +41,15 @@ func mapHandler(w http.ResponseWriter, req *http.Request) { if seed == "" { seed = time.Now().String() } - wastelands, err := strconv.Atoi(req.URL.Query().Get("wastelands")) + wastelands, err := strconv.Atoi(req.URL.Query().Get("w")) if err != nil { wastelands = 7 } - mountains, err := strconv.Atoi(req.URL.Query().Get("mountains")) + mountains, err := strconv.Atoi(req.URL.Query().Get("m")) if err != nil { mountains = 5 } - ruins, err := strconv.Atoi(req.URL.Query().Get("ruins")) + ruins, err := strconv.Atoi(req.URL.Query().Get("r")) if err != nil { ruins = 6 } @@ -63,12 +63,15 @@ func mapHandler(w http.ResponseWriter, req *http.Request) { } func indexHandler(w http.ResponseWriter, req *http.Request) { - log.Printf("GET / (%v)", req.RemoteAddr) + seed := generator.RandomSeed() + world := generator.New(11, 7, 5, 6, seed) + + log.Printf("GET / (%v) Seed: %v", req.RemoteAddr, seed) tpl, err := template.ParseFS(templateFiles, "templates/index.tpl.html") if err != nil { log.Fatal(err) } - tpl.Execute(w, nil) + tpl.Execute(w, world) } diff --git a/pkg/web/static/generator.js b/pkg/web/static/generator.js new file mode 100644 index 0000000..3e83561 --- /dev/null +++ b/pkg/web/static/generator.js @@ -0,0 +1,51 @@ +document.addEventListener('DOMContentLoaded', function() { + let generate = function(seed) { + let size = document.querySelector('input[name="size"]').value + let wastelands = document.querySelector('input[name="wastelands"]').value + let mountains = document.querySelector('input[name="mountains"]').value + let ruins = document.querySelector('input[name="ruins"]').value + + let map = document.querySelector('.map') + // Generate new random seed + let newMapUrl = '/map.svg?seed=' + seed + + '&s=' + size + + '&w=' + wastelands + + '&m=' + mountains + + '&r=' + ruins + document.querySelector('.map').setAttribute('src', newMapUrl); + document.querySelector('#map-link').setAttribute('href', newMapUrl); + }; + + let buttons = document.querySelectorAll('input[type="button"]') + Array.prototype.forEach.call(buttons, function(button, i) { + button.addEventListener('click', function(e) { + // Reset to default buttons + if (e.target.hasAttribute('data-default')) { + let defaultValue = e.target.getAttribute('data-default'); + let name = e.target.getAttribute('name').substr(8); + let targetInput = document.querySelector('input[type="text"][name="'+name+'"]') + targetInput.value = defaultValue; + } + + // Roll the dice + if (e.target.getAttribute('name') === 'random-seed') { + let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + let seed = ''; + for (let i=0; i<10; i++) { + let index = Math.floor(Math.random() * 25) + seed += chars[index] + } + + let seedElement = document.querySelector('input[name="seed"]'); + seedElement.value = seed; + generate(seed); + } + + // Refresh + if (e.target.getAttribute('name') === 'refresh') { + let seed = document.querySelector('input[name="seed"]').value; + generate(seed); + } + }) + }); +}); diff --git a/pkg/web/static/images/logo.jpg b/pkg/web/static/images/logo.jpg index 3b199ba..11ff490 100644 Binary files a/pkg/web/static/images/logo.jpg and b/pkg/web/static/images/logo.jpg differ diff --git a/pkg/web/static/styles.css b/pkg/web/static/styles.css index 4c73365..075bdf6 100644 --- a/pkg/web/static/styles.css +++ b/pkg/web/static/styles.css @@ -1,10 +1,38 @@ +body { + width: 900px; + margin: auto; +} + +h1 { + text-align: center; +} + p > img { - float: right; - width: 250px; + float: left; + width: 100px; + margin: 10px; } .map { - margin: auto; - display: block; - width: 350px; + float: right; + width: 450px; + margin: 20px; +} + +label { + width: 100px; + display: inline-block; + text-align: right; +} + +input[type="text"] { + width: 90px; +} +input[name="seed"] { + width: 250px; +} + +fieldset { + width: 370px; + margin: 10px 0; } diff --git a/pkg/web/templates/index.tpl.html b/pkg/web/templates/index.tpl.html index 2483e9d..da21f9f 100644 --- a/pkg/web/templates/index.tpl.html +++ b/pkg/web/templates/index.tpl.html @@ -7,9 +7,11 @@ +

Map Generator für "Der Kartograph"

+

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, @@ -17,8 +19,39 @@ Die generierten Karten entsprechen den erweiterten Regeln, können aber für etwas mehr Spaß angepasst werden.

- Neue Map generieren -

- + {{ with . }} +
+
+ Seed + + +
+ +
+ Spielfeldgröße + + +
+ +
+ Parameter + + + +
+ + + +
+ + + +
+
+ + + +
+ {{ end }}