README.md 7.45 KB
Newer Older
Allele Dev's avatar
Allele Dev committed
1 2 3 4 5
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**

- [Type-Assisted Speed Runs: A Haskell Web Services Tutorial](#type-assisted-speed-runs-a-haskell-web-services-tutorial)
6 7 8 9
- [Setup](#setup)
  - [Database](#database)
  - [Redis](#redis)
  - [Ad-hoc Testing](#ad-hoc-testing)
Allele Dev's avatar
Allele Dev committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
- [Contributing](#contributing)
- [Licensing](#licensing)
- [Project](#project)
  - [Overview](#overview)
  - [Project Setup: Making Things Build](#project-setup-making-things-build)
  - [Dependency Management: Gathering Your Tools](#dependency-management-gathering-your-tools)
  - [Directory Structuring: Laying Out a Consistent Foundation](#directory-structuring-laying-out-a-consistent-foundation)
  - [Data Modeling: Express Yourself](#data-modeling-express-yourself)
  - [Storage Layer: Databases and External Storage](#storage-layer-databases-and-external-storage)
  - [Responses and Requests: JSON Handling and Query Params](#responses-and-requests-json-handling-and-query-params)
  - [Endpoints and Controllers: Connecting All the Parts](#endpoints-and-controllers-connecting-all-the-parts)
  - [Logging: Auditing, Debugging, and Provenance](#logging-auditing-debugging-and-provenance)
  - [Trade-offs in Haskell: Partiality, Exceptions, and More](#trade-offs-in-haskell-partiality-exceptions-and-more)
  - [Ad-Hoc Testing: Seeing Things Go](#ad-hoc-testing-seeing-things-go)
  - [Other Tools](#other-tools)
  - [Potential Extensions](#potential-extensions)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Allele Dev's avatar
Allele Dev committed
29 30 31 32 33
# Type-Assisted Speed Runs: A Haskell Web Services Tutorial

Welcome! This tutorial develops a Haskell web service from
scratch. Here's an overview of the material to be covered:

Allele Dev's avatar
Allele Dev committed
34 35 36
# Setup

* Install [stack](https://github.com/commercialhaskell/stack)
Allele Dev's avatar
Allele Dev committed
37
* Clone the project: `git clone https://gitlab.com/queertypes/type-assisted-speed-runs.git`
38 39 40 41 42 43 44 45 46 47
* `cd` into the project
* You should see the following output, or close to it, from `ls`:

```bash
$ ls
changelog.md        docs      README.md  src
CODE_OF_CONDUCT.md  dump.rdb  Setup.hs   stack.yaml
dist                LICENSE   sql        type-assisted-speed-runs.cabal
```

Allele Dev's avatar
Allele Dev committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
* Run `stack setup` to get a Haskell compiler
* Run `stack build` to install dependencies and start learning!
* Run `stack run tasr-server` to run the server

## Database

This project requires postgreSQL for primary data storage. The easiest
way to get that running is to install it using your package manager.

Check out this [link](http://www.postgresql.org/download/) for next
steps. The default settings are:

* Database name: `strangeloop`
* Host: `localhost`
* Port: 5432
* User name: `strangeloop`
* Password: `cat`

Allele Dev's avatar
Allele Dev committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
Once you're able to connect, you should be able to create all the
required tables using three commands, two run as the superuser:

```sql
$ createdb strangeloop
$ psql strangeloop < sql/00-setup.sql
CREATE EXTENSION
CREATE ROLE
GRANT
CREATE SCHEMA
$ psql -h localhost strangeloop strangeloop < sql/01-players-runs-games.sql
Password for user strangeloop:
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
```

Allele Dev's avatar
Allele Dev committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
## Redis

Redis is used for session key management. The easiest way to get that
set up is to use your package manager.

A default instance of Redis should be fine. Specifcially:

* Port: 6379
* Host: `localhost`

## Ad-hoc Testing

I'll be running through the demo using the
[httpie](https://github.com/jkbrzt/httpie) command line request
generator. The following will probably also work:

* Chrome [Postman](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en)
* [cURL](http://curl.haxx.se/)

Use whatever you're comfortable using, as long as you can interact
with the server and see responses.

Allele Dev's avatar
Allele Dev committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
# Contributing

Contributions are welcome! Documentation, examples, code, and
feedback - they all help.

Be sure to review the included code of conduct. This project adheres
to the [Contributor's Covenant](http://contributor-covenant.org/). By
participating in this project you agree to abide by its terms.

# Licensing

This project is made available under the BSD3 license. These are
fairly liberal terms. Feel free to do what you need with the source,
as long as you give credit to the project maintainers.

See the included LICENSE file for more details.

# Project

We're going to build a speed-run tracking web site. A
[speed run](https://en.wikipedia.org/wiki/Speedrun) is a playthrough
of a game with the intent of completing it as quickly as possible.

This website will track the following entities:

* Users
* Games
* Runs

A user is a player with a registered account. We allow them to select
their user name, a display name, and an image to represent
themselves. Users are determined uniquely by the email address they
used to register.

For games, we track a title, and optionally, a publisher and
publication year. Games are determined uniquely by their title. Only
site administrators can add new games. Users can request that games be
added.

For runs, we track the run duration, evidence (a link to a video), the
user who submitted it, and the game it is for. Runs are determined by
a user/game pair. A user may only submit one run per game. A user may
choose to archive previous runs. These are stored separately and are
not used for ranking purposes. There are also two categories of runs,
each ranked separately. These are:

* Standard: no glitches or tools used
* Tool-assisted run: tools are used to make the game easier to play
* Glitch runs: exploits are used to achieve a faster completion time
* Tool-assisted glitch runs: both tools and glitches are leveraged

These are all ranked separately.

This identifies some auxiliary entities:

* Images (for games, user profiles/avatars)
* Rankings (by user, by game)

## Overview

* Build an HTTP/JSON API
  * Type-Assisted Speed Runs

## Project Setup: Making Things Build

* Project setup
  * cabal init
  * Adding dependencies
  * stack init

## Dependency Management: Gathering Your Tools

* Dependency management
  * Adding compiler flags
  * stack [build|test|haddock|bench|sdist]
  * How stack works, conceptually

## Directory Structuring: Laying Out a Consistent Foundation

* Directory structuring
  * Data
  * Control
  * {Application} TAS
    * Models
    * Database
    * Errors
  * API
  * Other categories

## Data Modeling: Express Yourself

* Products as Products
* Alternatives and Choices
* Optional Fields
* Mapping to Storage

## Storage Layer: Databases and External Storage

* Storage
  * Database interaction
  * Model<->Database

## Responses and Requests: JSON Handling and Query Params

* JSON [en|de]coding
  * FromJSON
  * ToJSON
  * Connecting to model

## Endpoints and Controllers: Connecting All the Parts

* Endpoint registration
  * Routes
  * Validation at controller level
  * Rich errors

## Logging: Auditing, Debugging, and Provenance

* Logging
  * fast-logger
  * Logging levels
  * Logging in IO
  * Logging structure: timestamp, hostname,

## Trade-offs in Haskell: Partiality, Exceptions, and More

* Making trade-offs
  * Exceptions
    * What can throw them with this stack?
    * Thoughts and opinions
  * Totality
    * Avoid: read, fromJust,

## Ad-Hoc Testing: Seeing Things Go

* Ad-hoc testing
  * HTTPie: sessions and all

## Other Tools

* Editors
* Linting
* More testing
* API Documentation

## Potential Extensions

* Game completion rate (e.g., Metroid 100% completion vs. arbitrary completion)