This service generates a simple railroad track map using the Wave Function Collapse algorithm as described by Oskar Stålberg.
For the implementation of the algorithm, we use go-wfc.
To test the service, simple run make run and you should find the
result in the output directory.
% make run
mkdir -p ./output
go run main.go --run-once
INFO: Image saved to: ./output/1733191573560971000.png
% open ./output/1733191573560971000.png
In its simplest form, the Wave Function Collapse algorithm tries to find a layout of
For our toy example, we pick three evenly spaced point on each side, take their respective RGB color
and hash them together into a single ConstrainId as shown below:
The following image shows two scenarios, one for a side-by-side match, and one where there is none.
All tiles used can be found in the ./tiles directory
To turn this program into an IVCAP service, we need to add the following:
- An HTTP
POST /handler to accept a request, create an image and return it - An HTTP
GET /_healtzhandler to indicate that the service is up - A
Dockerfileto dockerize the service - A
service.jsonfile to describe the service
The following code snippet at the end of main.go initialises and starts
a web server as well as implements the /_healtz endpoint
fmt.Printf("INFO:\tListening on port %d\n", *port)
http.HandleFunc("/", handler)
http.HandleFunc("/_healtz", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
s := fmt.Sprintf("{\"version\": \"%s\"}\n", VERSION)
w.Write([]byte(s))
})
if err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil); err != nil {
fmt.Printf("ERROR:\tServer problem - %v'\n", err)
}The actual service is implemented in the handler function:
type Request struct {
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Attempts int `json:"attempts,omitempty"`
}
func handler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
req := parse_request(w, r)
if req == nil {
return
}
images, err := load_tiles()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
output, err := collapseWave(images, req.Width, req.Height, req.Attempts)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
save_image(output, w)
return
} else {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
}
}It parses the incoming request as defined per Request. An example of a valid request
can be found in sample_request.json.
The Dockerfile packages this toy application into a Docker container which cna be uploaded to IVCAP.
The make docker-build target builds the container locally, make docker-run executes the application
inside the container and stores the result in the same location as make run (this assumes that your local file system can be easily mapped into the container)
To test the container in a context similar to IVCAP, first start the container as web server in one
terminal (make docker-serve). Then open a new terminal and run:
% make send-request
Status: 200
{"content-type":["image/png"],
"transfer-encoding":["chunked"]
}
result stored in ./output/2024-12-03T14:08:44+11:00.pngIf everything works, feel free to upload the docker package with make docker-publish.
The service.json file describes the service, the expected schema of both the incoming request as well as the responding result.
{
"$schema": "urn:ivcap:schema.service.2",
"$id": "#SERVICE_URN#",
"name": "Railroad Tracks via Wave Function Collapse algorithm",
"description": "This service generates a simple railroad track map ...",
"policy": "urn:ivcap:policy:ivcap.base.service",
"controller_schema": "urn:ivcap:schema.service.rest.1",
"controller": {
"$schema": "urn:ivcap:schema.service.rest.1",
"type": "object"
"command": [
"/app/main",
"--port",
"8080"
],
"port": 8080,
"package_urn": "#PACKAGE_URN#",
"ready_path": "/_healtz",
"request": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:sd.test:schema.railroad-collapse.request.1",
"properties": {
"width": {
"default": 8,
"description": "Number of tiles in x direction",
"title": "Width",
"type": "number"
},
...
},
...
},
"response": {
"$schema": "urn:ivcap:schema:binary-response",
"content-type": "image/png"
}
}
}In order to deploy this service to IVCAP, run the make service-register target.


