# Monadical Applicant Study Guide
*Originally published 2017-02-13 on [docs.sweeting.me](https://docs.sweeting.me/s/blog).*
Some resources and example projects for developers thinking about applying to Monadical.
Want to apply to Monadical? Go to our [team page](https://monadical.com/team#join) and click `Apply Now` at the bottom.
Here's some documentation links for things we use in the Monadical stack. Whether you're brushing up on your skills to [apply to Monadical](https://monadical.com/apply) or just interested in what technology we use, these are the resources to get started.
## Stack Documentation
Make sure to read our other technical [blog posts](https://monadical.com/blog) to learn about our design philosophies and approach to software architecture!
- Python Language
- Beginner: https://learnxinyminutes.com/docs/python/
- Beginner: https://wiki.python.org/moin/BeginnersGuide
- Beginner: https://docs.python.org/3/tutorial/index.html
- Docs: https://docs.python.org/3/
- Itermediate & Advanced: http://intermediate-and-advanced-software-carpentry.readthedocs.io/en/latest/day1.html
- PEP8: http://dcjtech.info/wp-content/uploads/2015/12/Python-Syntax-Checker-Codes-Cheatsheet.pdf
## Practice Projects
### Design Guidelines
#### The Frontend
#### The Backend
The backend must be written in Python 3.7. You may use any backend framework or ORM such as Django, Flask, Bottle, Pyramids/Pylons, etc.
All state must be stored in the backend in append-only fasion. This is a design pattern we use frequently at Monadical, so we’d like to make sure you’re comfortable working with immutable, append only data structures.
The key idea is that any database can be abstracted as a log of changes to some initial state, such as game moves or canvas clicks. You should store the full log and a function that transforms that log into whatever state the frontend needs. For example, for a banking app you would store a list of the transactions in and out of a users wallet, and use a function to add up the credits & debits to display their total balance.
To become more familiar with append-only log-structured data, read this article:
The frontend and backend may interact via REST API, or websocket. You can choose how to implement it, but real-time streaming can be tricky, so you may choose to send drawing strokes or board moves when a user clicks a button instead of sending events continuously. If you’re familiar with websockets, then we recommend using them instead.
Standard FizzBuzz, Google it.
#### Snake Game
Find the hidden bug in the code, and change the behavior to make the snake die when hitting a wall instead of wrapping around the screen.
#### Multiplayer Game
Build a multiplayer game frontend & backend with django-channels and redux-time. An example would be a drawing game where one player's canvas drawing is synced to another person's scree, and they have to guess which work the user is drawing out of a selection, within a certain amount of time. It should use websockets to transmit the connection state in real time between players, but it can be anything realtime, it doesn't have to be a drawing game. Games with moving characters are harder because collision physics over a connection with latency is difficult to syncronize.
#### Simple Database App
Write a small React redux application that displays a simple list of key:values in the frontend as a table with two columns (keys and values). It should store data in the redux store, and allow the user to add a new key : value, or delete an existing one. When you come in you can work on adding one or more of these features:
- ability to filter the table using a search box
- persist the table in localStorage
- ability to download the table as JSON or CSV
You should try to make the table look reasonably nice with CSS, you may use a CSS framework like bootstrap or material design, or hand-code the CSS, although don't over-engineer it.
#### Leaderboard UX
Requires creativity, UX design, user & competitor research, and honing in loose design requirements come up with a good experience.
Design an interactive leaderboard & player ranking interface in React that encourages players to earn more chips and improve their skills. It should balance showing stats & info with remaining clean and encouraging users to take actionable steps to play against more people or learn more theory.
#### Tic Tac Toe game
Write a program that lets two humans play a game of Tic Tac Toe in a terminal. The program should let the players take turns to input their moves. The program should report the outcome of the game.
When you come in, we will pair on adding support for a computer player to your game. We can start with random moves and then work on making the AI smarter after that.
#### Lisp parser
Write code that takes some Lisp code and returns an abstract syntax tree. The AST should represent the structure of the code and the meaning of each token. For example, if your code is given "(first (list 1 (+ 2 3) 9))", it could return a nested array like ["first", ["list", 1, ["+", 2, 3], 9]].
When you come in, we will pair on writing an interpreter to run the AST. We can start by implementing a single built-in function (for example, +) and add more if we have time.
#### Space Invaders
Write a game of Space Invaders that has computer-controller enemies that move left and right automatically and a human-controlled player that you can move left and right with the arrow keys.
When you come in, we can add the ability to shoot bullets at the enemies and track your score.
#### Video conference app
Requires researching a complex API and implementing a redux-based store to manage a stateful API in a functional deterministic manner.
Build a video conferencing app with WebRTC that has clean management of connection state and an easy UX to video chat with other people by sharing a websocket link.
#### Shared Whiteboard
This is a two-person shared chalkboard/whiteboard, where there is a canvas that both peoplecan draw on, each person’s stokes are visible in a color specific to that person.
The take-home task is to start by allowing a single person to draw on a canvas, and download their drawing from the server as TXT, CSV, or JSON file. The drawing should be saved continously to the server, as an append-only log of strokes, so that if the user refreshes it is displayed without any data loss.
Then, during the interview we will pair on adding the ability for a second user to share the canvas in real-time and color each persons strokes with a color unique to that user.
#### Pictionary Game
This is a game where one player draws a picture, and the other player tries to guess which word the person is trying to draw out of a selection. The objective is to guess the word as soon as possible, before the person has drawn the entire thing (a popular app that did this is Words with Friends), so you should display a timer to both users once they start drawing.
The take home task is to allow a single person’s drawing to be displayed on another person’s screen in real-time.
the pairing task is to add the words for the first person to draw, and build a system for the second person to select the right word and display whether they won or lost.
#### Magnetic-cave Game
This is essentially connect-four, but the pieces stack on either side of the board instead of bottom-up.
Two players see a board, which is a grid of 7 rows and 7 columns. They take turn adding pieces to a row, on one of the sides. The pieces stack on top of each other, and the game ends when there are no spaces left available, or when a player has four consecutive pieces on a diagonal, column, or row.
For example, the board might look like this:
0 [ _ _ _ _ _ _ _ ]
1 [ o x _ _ _ _ o ]
2 [ x _ _ _ _ _ x ]
3 [ x _ _ _ _ _ o ]
4 [ o _ _ _ _ _ _ ]
5 [ _ _ _ _ _ _ _ ]
6 [ _ _ _ _ _ _ _ ]
in this case, it is x’s turn. If x plays (2, R), the board will look like this:
0 [ _ _ _ _ _ _ _ ]
1 [ o x _ _ _ _ o ]
2 [ x _ _ _ _ x x ]
3 [ x _ _ _ _ _ o ]
4 [ o _ _ _ _ _ _ ]
5 [ _ _ _ _ _ _ _ ]
6 [ _ _ _ _ _ _ _ ]
The take-home task is to implement the 2-player version of this game, where each player sees the board in their frontend and can place moves that the other player sees, and the game should display “player 1 won” “player 2 lost” when the game is complete.
The pairing task is to implement a single-player mode, starting with the computer placing random moves, and moving on to implementing an AI that’s a little smarter with some basic heuristics.
### Dev-Ops Project
**Overview:** Your goal is to set up a simple hello-world Django/Python app called "banana" on a server. The server should be running Nginx >=1.15, Postgresql >=11, Python >=3.7. It should store all its code and data in one place, with simple server-side bash commands available for deploying, updating, and doing backups. The stack outlined in this task is very similar to what we run internally, so it's a good representation of the real dev-ops tasks you'd be assigned if hired.
**Timeline:** We expect this task to take between 2-6 hours, depending on how comfortable you are with the technologies and patterns involved. Time is not used as a grading factor though, so feel free to take as long as you need (up to six weeks if necessary, e.g. if you're busy with your current day-job).
**Costs:** As it involves purchasing a domain and a VPS server, we're happy to transfer you the ~$10 USD needed to get started, or we can send it afterwards once you know the total ($15 maximum). We recommend the $3.50/mo Vultr.com droplet, but you may use any hosting provider you're comfortable with.
**Process:** You can code the setup manually, or you may use orchestration/deploy tools like Ansible/Docker/Puppet/Chef/etc, it's up to you. Results are partly graded on simplicity / minimalism, so optimize for having as little uncessary config as possible. Make sure all config and scripts used for setup are placed in version control. We use `supervisord` and `docker-compose` internally, so we ask that applicants use one or both of those for process management, but the server setup process can still be automated with other tools like Ansible/Chef/etc, just make sure to provide any Ansible playbooks or equivalents when submitting your final setup.
**Goals:** The goal of this task is to evaluate your level of comfort with setting up and securing common backend stacks in Unix environments. If you don't manage to complete all the tasks exactly as described, that's ok, you'll have an opportunity to explain which tasks were skipped or modified during the call. The final setup doesn't have to match the description exactly, the end goal is just to make sure it works and that the choices made along the way were reasonable, not to test your ability to strictly adhere to a spec.
**Security Model:** For this task you can assume the server is running in a trusted hosting environment with only root admins having shell access, there is no need to use disk encryption or guard exessively against internal attacks, just make sure to change SSH to port 44 and ensure sure only 44, 80, and 443 are publicly accessible (e.g. no need to install fail2ban).
**Before starting:** read this post about how Monadical manages servers, and try to match the style outlined when you build your own:
**When finished:** enable access to the server using SSH with the following key:
`ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMdwUnQvH0opeOLJi3HTBIHKMgOIAwBNfWdZUa7gWZWD [email protected]`, and send us the public IP. During the interview call afterwards, we will SSH in and inspect the setup and you'll walk us through your setup over the call, explaining any decisions made and answering any questions we might have. We'll ask you to run the scripts in `bin/` on the call as well to confirm they work.
Don't hesitate to ask if you have questions about this task, the interview process, or Monadical in general! Just send me an email here:
<img src="https://i.imgur.com/4w0TJur.png" height="30px">
##### Server Setup
- must be on a clean Ubuntu 19.04 install (no "one-click" setups from AWS, DigitalOcean, etc.)
- must be running nginx, postgres, and django, managed by a service manager other than `systemd`/`initd`, you can use `supervisord` or `docker-compose`
- app code, data, binaries, config, and backups must be stored entirely in subfolders under `/opt/banana` (hint, use a virtualenv for the code, and supervisord/docker to save output to logfiles in `./data/logs`)
- app must be an empty django app created using `django-admin startproject banana` (you can fork https://github.com/Monadical-SAS/example-devops-app, don't waste time writing code in the app, this project is testing your devops skills, not your python backend skills)
- django must point to the local PostgreSQL v11 database for data
- nginx must be running in front of django, serving staticfiles directly from the filesystem (proxying only page requests to Django)
- must have 4 easily executable bash scripts in `/opt/banana/bin` (these should just contain the ~1-10 lines of bash needed to accomplish the task, they shouldn't be complicated):
+ `bin/stop`: stop django, nginx, and postgresql
+ `bin/start`: start django, nginx, and postgresql
+ `bin/deploy`: pull the latest version of the app code from github, run migrations, and restart the necessary services
+ `bin/backup`: dump the postgresql database to a `.sql` file in `/opt/banana/data/backups`
- for simplicty and time-savings, we recommend just running the app with django `runserver` in `DEBUG=False` mode and `--noreload` passed, with no WSGI server between django and nginx
##### Network Setup
- Must have a public IPv4 address
- Must have SSH open only on port 44 (not 22), accepting pubkey authentication (no passwords)
- Must have a valid, public SSL certificate (using letsencrypt or CloudFlare's free tier)
- Must redirect all port 80 HTTP requests to HTTPS
- Django runserver and Postgres must not be publicly accessable via WAN
- Must have no other ports besides 80, 443, and 44 publicly accessable
##### Bonus Points
The dev-ops take-home project described above is already a decent amount of work, but that's because we're currently looking for relatively experienced devops engineers that are already comfortable setting up this type of server environment. If this task sounds easy and you feel it's not enough to show off your awesome chops, we've provided some additional tasks below as inspiration, but feel free to add anything else you feel would improve the setup.
Keep in mind, simplicity is key, this is not a production application with all its associated complexity, so try to keep it as small and lean as you can. Part of our grading criteria is how well applicants can accomplish this setup without adding lots of unecessary config and management overhead that doesn't provide tangible security or ops value.
- store all logs, cache files, tmp files, and other data in `/opt/banana/data` (this includes nginx logs, django logs, postgres logs, and the postgresql database files)
- make all code and data files only be readable/writable by their respective users and root (i.e. run nginx and django as `www-data`, postgres as the `postgres` user, etc.)
- accept http2 requests and return http2 responses (using the nginx http2 module)
- in `bin/backup`: compress the backups with gzip and rsync them to an external server passed as `$1`
- backup and deploy automatically whenever the code on the github `master` branch changes
- log ssh access events and any shell commands run to a file in `/opt/banana/data/logs`
- improve app security by servering better HTTP security headers (`X-Frame-Options`, `X-Content-Type-Options`, `X-XSS-Protection`, `Referrer-Policy`, `Strict-Transport-Security`, and any others you want to add)
- use the `bjoern` WSGI server or `django-channels`'s `runworker` to serve the app to nginx
- close port 80 and 443 by using a cloudflare argo tunnel to serve the app (which avoids exposing the app server's IP address to the public)
- do the whole thing on FreeBSD/OpenBSD/Nix/Debian instead of Ubuntu
- extreme bonus points: set up multiple web worker servers with one database server, with orchestration like Puppet/Chef/Ansible/Kubernetes/etc)