# Poke Stitch ## Exercise For Go Trainings The [PokeApi](https://pokeapi.co/) offers a web API through which you can retrieve data about Pokemons. In this exercise, you build a webserver that queries the *PokeApi* in the background and creates a stitched (=combined) image of Pokemon sprites. ![Output](https://github.com/rstropek/golang-samples/blob/master/hello-go/poke-stitch/pikachu.png?raw=true) ## Requirements Functional requirements: * Implement a webserver with Go * The webserver must offer one route (e.g. *http://localhost:8080/poke-stitch?pokemon=bulbasaur* where *bulbasaur* is the name of a Pokemon) * The webserver has to return `http.StatusBadRequest` (`w.WriteHeader(http.StatusBadRequest)`) if the pokemon name is missing in the query string * In case of any other error, return `http.StatusInternalServerError`. Returning additional error details is not required in this sample. * The route has to query the *PokeApi* (e.g. *https://pokeapi.co/api/v2/pokemon/bulbasaur*) to retrieve the Pokemon sprites (up to 8 images stored in JSON property *sprites*). * All available sprites have to be stitched together (=combined) into a single image in which two sprites are displayed side by side. * The webserver has to return the generated, combined image to the web client. Non-functional requirements: * After building a working prototype, try to get the sprite images in parallel using Goroutines. ## Tips ### Webserver * You can use the sample [*03-simple-web-server](https://github.com/rstropek/golang-samples/blob/master/go-microservices/03-simple-web-server/web.go) as a starting point. * Optionally, you can add graceful shutdown as shown in [04-advanced-web-server](https://github.com/rstropek/golang-samples/blob/master/go-microservices/04-advanced-web-server/web.go) ### Sending Web Requests * You can send web requests to the *PokeApi* with Go's `http.Get` helper method. [The documentation](https://pkg.go.dev/net/http#example-Get) contains an example. * To reduce the amount of code you need to write yourself, here is the data structure that can receive the Pokemon sprite from the *PokeApi*: ```go type pokemon struct { Sprites pokemonSprites `json:"sprites"` } type pokemonSprites struct { BackDefault string `json:"back_default"` BackFemale string `json:"back_female"` BackShiny string `json:"back_shiny"` BackShinyFemale string `json:"back_shiny_female"` FrontDefault string `json:"front_default"` FrontFemale string `json:"front_female"` FrontShiny string `json:"front_shiny"` FrontShinyFemale string `json:"front_shiny_female"` } ``` ### Images * Go has 2D image functionality built in ([`image` package](https://pkg.go.dev/image)) * To make combining the images easier, consider the package [*go-image-merge*](https://github.com/ozankasikci/go-image-merge). It is a lightweight package making combining images relatively simple. **Note:** In order to get the latest 0.2.3 preview version, run *go get github.com/ozankasikci/go-image-merge@66fdff08137800ab01d23717d10b2a0b663efe17* (where *66fd...* is the latest git commit in the repository at the time of writing this guide). Here is a code sample for how to combine four images with *go-image-merge*: ```go import ( ... gim "github.com/ozankasikci/go-image-merge" ) ... // `images` contains a slide or channel of `image.Image` objects // Build a data structure containing all source images grids := make([]*gim.Grid, 0) for img := range images { grids = append(grids, &gim.Grid{Image: img}) } // Combine the images rgba, err := gim.New(grids, 2 /* columns */, 2 /* rows; you have to calculate this value */).Merge() ... // Encode the combined image into a PNG image b := new(bytes.Buffer) wr := bufio.NewWriter(b) err = png.Encode(wr, rgba) wr.Flush() // b now contains the bytes of the combined PNG image ... ```