While needing a quick break from developing, I like to solve a jigsaw puzzle or two, usually using the website Jigidi, and I felt intrigued by the idea of competing to see who could solve it the fastest. Jigidi already allows you to do so, but it’s hard to find puzzles a lot of people have solved/a lot of competition. I even tried contacting them about it, requesting a simple list of the most solved puzzle, but that was not in their interests for some reason. So I decided to give it a try myself.
I wanted a challenging solution to develop, so in addition to better search and leaderboards, I also wanted to add real-time co-op/collaboration so multiple people could solve the puzzle together.
But before I got to that, I started by making the core of the application, the jigsaw-solving window. I tried going with different 2D JS Game engines, but all of them seemed to be a pretty big overkill when looking at what I needed it for. So I simply used an HTML5 Canvas in 2D Context.
To generate the different shapes, I developed a generator that outputs a list of SVG-Paths, which then could be displayed on the canvas and the picture put on top using the masking feature of canvases. After polishing it for a while I was pretty pleased with the result as it felt responsive to the user, while still be configurable in many ways, such as snapping distance, multiple shapes, puzzle and so on.
After having dealt with SVGs, collision detection, etc. I needed a fun feature to work on, so I wanted to integrate one of AWS’s APIs into my application, mostly as I had a relevant class on it at the time. After looking around I choose to go with the Rekognition API, as it allowed to check pictures for any explicit content such as nudity and denying it if any was found with a certain confidence. In addition to checking for explicit content, it also returned a list of tags of objects present in the picture, for example, if it was a picture of a car, it would tag it as the car, maybe the settings it was in and so on., each of these tags are then saved and used for search, meaning the user could search for puzzle without the uploader having to tag it themselves.
Then I started working on the collaboration feature, and early on I discovered it would be a pretty big task since most of the jigsaw logic was written in the client and now had to be done server-side. So after converting it over to C#, I had a functional prototype, but most of the puzzle-generator didn’t get converted, so for now, all the bricks are square. The client receives all the shapes from the server, in unknown order and without knowing where the bricks should be placed, hopefully preventing a little bit of cheating.
But given almost everything the user did had to go through the server, a noticeable delay was inevitable and that’s not acceptable in a competitive game, so while researching ways to circumvent it without given the client too much information about the game, which would allow cheating, I got busy with some other things and the project stood still.
To conclude it, I developed a working prototype with the features I originally wanted which was collaboration, search, and leaderboards.
List of features:
- Authentication & Authorization using IdentityServer4
- Fully Docker-ized
- Angular 7
- Metrics using AppMetrics for collecting, Prometheus for storage and Grafana for display
- Real-Time collaboration using WebSockets and SignalR
- Image storage using Minio (S3 Compatible)
- Image tagging & moderation using AWS Rekognition
- Search for image tags and title using ElasticSearch
- Auto-deploy using Jenkins triggered by git-hook
- Hosted on a DigitalOcean Droplet