Add docs headings to mainb server code

Add docs headings to mainb server code

    "use strict"

    express     = require 'express'
    raven       = require 'raven'

    system      = require './system'
    collection  = require './collection'
    document    = require './document'

## Init

    app = express()

## Authentication

This routine is called for all request to the API. It is reponsible for
authenticating the user by validating the `api\_key`. It then sets some request
session variables so they become accessible throughout the entire system during
the rquest.

In future versions of the API this routine will also check the request quota and
blocking the user if the quota is full.

    app.use '/', (req, res, next) ->

      key = req.query.api_key

      return res.json 403, message: 'API key missing' if not key
      return res.json 401, message: 'API key invalid' if not apiKeys[key]

      req.key = key
      req.usr = apiKeys[key]

      next()

## Configuration

    app.use(express.favicon())
    app.use(express.logger(':date :remote-addr - :method :url :status :res[content-length] - :response-time ms')) if not process.env.SILENT
    app.set('json spaces', 0) if app.get('env') isnt 'testing'
    app.use(express.compress())
    app.use(express.methodOverride())
    app.use(express.json())
    app.disable('x-powered-by')
    app.enable('verbose errors')
    app.set 'port', process.env.PORT_WWW or 8080
    app.use(app.router)
    app.use(raven.middleware.express(process.env.SENTRY_DNS)) if process.env.SENTRY_DNS

## Error handling

This is the error handler. All errors passed to `next` or exceptions ends up
here. We set the status code to `500` if it is not already defined in the
`Error` object. We then print the error mesage and stack trace to the console
for debug purposes.

Before returning a response to the user the request method is check. HEAD
requests shall not contain any body – this applies for errors as well.

    app.use (err, req, res, next) ->
      res.status(err.status or 500)

      console.error err.message
      console.error err.stack

      return res.end() if req.method is 'HEAD'
      return res.json message: err.message or 'Ukjent feil'

This the fmous 404 Not Found handler. If no route configuration for the request
is found, it ends up here. We don't do much fancy about it – just a standard
error message and HTTP status code.

    app.use (req, res) -> res.json 404, message: "Resurs ikke funnet"

## API keys

This is the dirty part. Here are all the keys to the kingdom. These will be
moved to the database and retrieved when the server starts. Just need to find
the time to do it.

    apiKeys =
      dnt: 'DNT'
      nrk: 'DNT'

      '30ad3a3a1d2c7c63102e09e6fe4bb253': 'TurApp'
      'b523ceb5e16fb92b2a999676a87698d1': 'Pingdom'

      '4c802ac2315ab24db9c992cc6eea0278': 'DNT' # ETA
      'de2986ac75c5af9d7f92a26f37dc1b77': 'DNT' # sherpa2.api
      '5dd5a39057cb479c3c4bce7f9eae5e6c': 'DNT' # dev.ut.no
      '146bbe01b477e9e07e85e0ddd3f5095a': 'DNT' # beta.ut.no
      'e6fa27292ffbcc689c49179c47bc708e': 'DNT' # prod.ut.no

## GET /

    app.get '/', (req, res) ->
      res.json message: 'Here be dragons'

## GET /system

Hsssssj!!! Don't tell anyone aboyt the secret system API endpoint!

    app.get '/system', system.info

## GET /CloudHealthCheck

> So...You’re seeing the dotCloud active health check looking to make sure that
> your service is up. There is no way for you to disable it, but you can prevent
> it and you can handle it [1]!

[1] [dotCloud](http://docs.dotcloud.com/tutorials/more/cloud-health-check/)

    app.get '/CloudHealthCheck', system.check

## GET /objekttyper

    app.get '/objekttyper', (req, res, next) ->
      res.json 200, ['turer', 'steder', 'områder', 'grupper', 'arrangementer', 'bilder']

## ALL /{collection}

    app.param 'collection', collection.param
    app.all '/:collection', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then collection.options req, res, next
        when 'HEAD', 'GET' then collection.get req, res, next
        when 'POST' then collection.post req, res, next
        when 'PUT'  then collection.put req, res, next
        when 'PATCH' then collection.patch req, res, next
        else res.json 405, message: 'HTTP method not supported'

## ALL /{collection}/{objectid}

    app.param 'objectid', document.param
    app.all '/:collection/:objectid', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then document.options req, res, next
        when 'HEAD', 'GET' then document.get req, res, next
        when 'PUT' then document.put req, res, next
        when 'PATCH' then document.patch req, res, next
        when 'DELETE' then document.delete req, res, next
        else res.json 405, message: 'HTTP method not supported'

## Start

Ok, so if the server is running in stand-alone mode i.e. there is not
`module.parent` then continue with starting the databse and listening to a port.

    if not module.parent
      require('./db/redis')
      require('./db/mongo').once 'ready', ->
        console 'Database is open...'

        app.listen app.get('port'), ->
          console.log "Server is listening on port #{app.get('port')}"

However, if there is a `module.parent` don't do all the stuff above. This means
that there is some program that is including the server from it, e.g a test, and
hence it should not listen to a port for incomming connections and rather just
return the application instance so that we can do some testing on it.

    else
      module.exports = app

    "use strict"

    express     = require 'express'
    raven       = require 'raven'

    system      = require './system'
    collection  = require './collection'
    document    = require './document'

    app = express()

This routine is called for all request to the API. It is reponsible for
authenticating the user by validating the `api\_key`. It then sets some request
session variables so they become accessible throughout the entire system during
the rquest.

In future versions of the API this routine will also check the request quota and
blocking the user if the quota is full.

    app.use '/', (req, res, next) ->

      key = req.query.api_key

      return res.json 403, message: 'API key missing' if not key
      return res.json 401, message: 'API key invalid' if not apiKeys[key]

      req.key = key
      req.usr = apiKeys[key]

      next()

Now configure the Express server so it is ready to run.

    app.use(express.favicon())
    app.use(express.logger(':date :remote-addr - :method :url :status :res[content-length] - :response-time ms')) if not process.env.SILENT
    app.set('json spaces', 0) if app.get('env') isnt 'testing'
    app.use(express.compress())
    app.use(express.methodOverride())
    app.use(express.json())
    app.disable('x-powered-by')
    app.enable('verbose errors')
    app.set 'port', process.env.PORT_WWW or 8080
    app.use(app.router)
    app.use(raven.middleware.express(process.env.SENTRY_DNS)) if process.env.SENTRY_DNS

This is the error handler. All errors passed to `next` or exceptions ends up
here. We set the status code to `500` if it is not already defined in the
`Error` object. We then print the error mesage and stack trace to the console
for debug purposes.

Before returning a response to the user the request method is check. HEAD
requests shall not contain any body – this applies for errors as well.

    app.use (err, req, res, next) ->
      res.status(err.status or 500)

      console.error err.message
      console.error err.stack

      return res.end() if req.method is 'HEAD'
      return res.json message: err.message or 'Ukjent feil'

This the fmous 404 Not Found handler. If no route configuration for the request
is found, it ends up here. We don't do much fancy about it – just a standard
error message and HTTP status code.

    app.use (req, res) -> res.json 404, message: "Resurs ikke funnet"

This is the dirty part. Here are all the keys to the kingdom. These will be
moved to the database and retrieved when the server starts. Just need to find
the time to do it.

    apiKeys =
      dnt: 'DNT'
      nrk: 'DNT'

      '30ad3a3a1d2c7c63102e09e6fe4bb253': 'TurApp'
      'b523ceb5e16fb92b2a999676a87698d1': 'Pingdom'

      '4c802ac2315ab24db9c992cc6eea0278': 'DNT' # ETA
      'de2986ac75c5af9d7f92a26f37dc1b77': 'DNT' # sherpa2.api
      '5dd5a39057cb479c3c4bce7f9eae5e6c': 'DNT' # dev.ut.no
      '146bbe01b477e9e07e85e0ddd3f5095a': 'DNT' # beta.ut.no
      'e6fa27292ffbcc689c49179c47bc708e': 'DNT' # prod.ut.no

## GET /

    app.get '/', (req, res) ->
      res.json message: 'Here be dragons'

## GET /system

Hsssssj!!! Don't tell anyone aboyt the secret system API endpoint!

    app.get '/system', system.info

## GET /CloudHealthCheck

> So...You’re seeing the dotCloud active health check looking to make sure that
> your service is up. There is no way for you to disable it, but you can prevent
> it and you can handle it [1]!

[1] [dotCloud](http://docs.dotcloud.com/tutorials/more/cloud-health-check/)

    app.get '/CloudHealthCheck', system.check

## GET /objekttyper

    app.get '/objekttyper', (req, res, next) ->
      res.json 200, ['turer', 'steder', 'områder', 'grupper', 'arrangementer', 'bilder']

## ALL /{collection}

    app.param 'collection', collection.param
    app.all '/:collection', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then collection.options req, res, next
        when 'HEAD', 'GET' then collection.get req, res, next
        when 'POST' then collection.post req, res, next
        when 'PUT'  then collection.put req, res, next
        when 'PATCH' then collection.patch req, res, next
        else res.json 405, message: 'HTTP method not supported'

## ALL /{collection}/{objectid}

    app.param 'objectid', document.param
    app.all '/:collection/:objectid', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then document.options req, res, next
        when 'HEAD', 'GET' then document.get req, res, next
        when 'PUT' then document.put req, res, next
        when 'PATCH' then document.patch req, res, next
        when 'DELETE' then document.delete req, res, next
        else res.json 405, message: 'HTTP method not supported'

Ok, so if the server is running in stand-alone mode i.e. there is not
`module.parent` then continue with starting the databse and listening to a port.

    if not module.parent
      require('./db/redis')
      require('./db/mongo').once 'ready', ->
        console 'Database is open...'

        app.listen app.get('port'), ->
          console.log "Server is listening on port #{app.get('port')}"

However, if there is a `module.parent` don't do all the stuff above. This means
that there is some program that is including the server from it, e.g a test, and
hence it should not listen to a port for incomming connections and rather just
return the application instance so that we can do some testing on it.

    else
      module.exports = app


Fix the next-match situation

Fix the next-match situation

Next Match Manager
==================

We first set everything in a callback, so that it is invoked only
after the loading of the DOM.

    $ ->

Input
-----

We need both the next match and the list of teams as our inputs.

        inputStream = Bacon.combineTemplate
            teams: Data.teams
            next: NextMatch

List Management
---------------

We use D3 to set the data within the list.

        inputStream.onValue (state) ->
            return unless state.next?

            nodeHTML = (entry) ->
                "<li>#{state.teams[entry].name}</li>"

            DisplayInformation '.next-match-teams',
                               state.next.teams,
                               'li', nodeHTML

Time Display
------------

We use the next match alone for the display of its start time.

    NextMatch.onValue (match) ->
        if match?
            $('.next-match-time').text(FormatTime(FromUNIX(match.start),
                                                        false))
        else
            $('.next-match-time').text('-')

Next Match Manager
==================

We first set everything in a callback, so that it is invoked only
after the loading of the DOM.

    $ ->

Input
-----

We need both the next match and the list of teams as our inputs.

        inputStream = Bacon.combineTemplate
            teams: Data.teams
            next: NextMatch

List Management
---------------

We use D3 to set the data within the list.

        inputStream.onValue (state) ->
            return unless state.next?

            nodeHTML = (entry) ->
                "<li>#{state.teams[entry].name}</li>"

            listItems = d3.select('.next-match-teams')
                          .selectAll('li')
                          .data(state.next.teams)
                          .html(nodeHTML)

            listItems.enter()
                     .append('li')
                     .html(nodeHTML)

            listItems.exit()
                     .remove()

Time Display
------------

We use the next match alone for the display of its start time.

    NextMatch.onValue (match) ->
        if match?
            $('.next-match-time').text(FormatTime(FromUNIX(match.start),
                                                        false))
        else
            $('.next-match-time').text('-')


Fixed a bug causing corruption when inverting a matrix in-place.

Matrices are arrays of 16 numbers forming a 4x4 matrix.

    temp1 = []
    temp2 = []
    rotationTemp = []
    tempVector = []
    tempVectorFrom = []
    tempVectorTo = []
    fromTemp = []
    toTemp = []
    tempVectorX = []
    tempVectorY = []
    tempVectorZ = []

    makeRotate = (axis1, axis2, axis3, axis4) ->
        temp3 = []
        rotationTemp.push temp3
        (radians, output, local) ->
            sin = Math.sin radians
            cos = Math.cos radians
            temp3[axis1] = cos
            temp3[axis2] = -sin
            temp3[axis3] = sin
            temp3[axis4] = cos
            if local
                module.exports.multiply temp3, output, output
            else
                module.exports.multiply output, temp3, output
            return

    vector = require "./vector.litcoffee"

    module.exports =

Given a matrix, calling the "identity" property writes the identity matrix to
it.

        identity: (output) ->
            for row in [0...4]
                for column in [0...4]
                    output[row * 4 + column] = if row is column then 1 else 0
            return

Given two matrices, calling the "copy" property copies every component from the
first to the second.

        copy: (input, output) ->
            output[index] = value for value, index in input
            return

Given three matrices, calling the "multiply" property multiplies the first two
together and writes the result to the third.

        multiply: (a, b, output) ->
            module.exports.copy a, temp1
            module.exports.copy b, temp2

            for row in [0...4]
                for column in [0...4]
                    temp = 0
                    for component in [0...4]
                        temp += temp1[component * 4 + column] * temp2[row * 4 + component]
                    output[row * 4 + column] = temp
            return

Given a number of radians and a matrix, calling the "rotateX" property modifies
the matrix to have been rotated by that number of radians about the X axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateX: makeRotate 5, 6, 9, 10

Given a number of radians and a matrix, calling the "rotateY" property modifies
the matrix to have been rotated by that number of radians about the Y axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateY: makeRotate 0, 2, 8, 10

Given a number of radians and a matrix, calling the "rotateZ" property modifies
the matrix to have been rotated by that number of radians about the Z axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateZ: makeRotate 0, 1, 4, 5

Given a vector specifying the scaling factor on each axis and a matrix, calling
the "scale" property scales the matrix by those scaling factors.

        scale: (vector, output) ->
            output[index] *= vector[0] for index in [0...4]
            output[index] *= vector[1] for index in [4...8]
            output[index] *= vector[2] for index in [8...12]
            return

# translate

- A vector to translate by.
- A matrix to translate.
- When truthy, the translation is applied in local space, otherwise it is
  applied in global space.

        translate: (v, output, local) ->
            if local
                tempVectorX[0] = output[0]
                tempVectorX[1] = output[1]
                tempVectorX[2] = output[2]

                tempVectorY[0] = output[4]
                tempVectorY[1] = output[5]
                tempVectorY[2] = output[6]

                tempVectorZ[0] = output[8]
                tempVectorZ[1] = output[9]
                tempVectorZ[2] = output[10]

                tempVector[0] = vector.dot tempVectorX, v
                tempVector[1] = vector.dot tempVectorY, v
                tempVector[2] = vector.dot tempVectorZ, v
                module.exports.translate tempVector, output
            else
                output[3] += v[0]
                output[7] += v[1]
                output[11] += v[2]
            return

Given a matrix, X, Y, Z and W values (defaulting to 0, 0, 0 and 1 respectively
if not given), calling the "apply" property returns an array of four numbers
representing the transformed vector.

        apply: (matrix, x, y, z, w) ->
            if x is undefined then x = 0
            if y is undefined then y = 0
            if z is undefined then z = 0
            if w is undefined then w = 1

            [
                x * matrix[0] + y * matrix[1] + z * matrix[2] + w * matrix[3]
                x * matrix[4] + y * matrix[5] + z * matrix[6] + w * matrix[7]
                x * matrix[8] + y * matrix[9] + z * matrix[10] + w * matrix[11]
                x * matrix[12] + y * matrix[13] + z * matrix[14] + w * matrix[15]
            ]

Given a matrix, input vector and output vector, calling the "applyToVector"
property writes the input vector transformed by the matrix to the output vector.

        applyToVector: (matrix, input, output) ->
            vector.copy input, tempVector
            output[0] = tempVector[0] * matrix[0] + tempVector[1] * matrix[1] + tempVector[2] * matrix[2] + matrix[3]
            output[1] = tempVector[0] * matrix[4] + tempVector[1] * matrix[5] + tempVector[2] * matrix[6] + matrix[7]
            output[2] = tempVector[0] * matrix[8] + tempVector[1] * matrix[9] + tempVector[2] * matrix[10] + matrix[11]
            return

Given a matrix and output vector, calling the "getTranslation" property writes
the translation applied by the matrix to the output vector.

        getTranslation: (matrix, output) ->
            output[0] = matrix[3]
            output[1] = matrix[7]
            output[2] = matrix[11]

Given a matrix and output vector, calling the "getX" property writes the vector
of the matrix's X axis (a scaled normal) to the output vector.

        getX: (matrix, output) ->
            output[0] = matrix[0]
            output[1] = matrix[4]
            output[2] = matrix[8]

Given a matrix and output vector, calling the "getY" property writes the vector
of the matrix's Y axis (a scaled normal) to the output vector.

        getY: (matrix, output) ->
            output[0] = matrix[1]
            output[1] = matrix[5]
            output[2] = matrix[9]

Given a matrix and output vector, calling the "getZ" property writes the vector
of the matrix's Z axis (a scaled normal) to the output vector.

        getZ: (matrix, output) ->
            output[0] = matrix[2]
            output[1] = matrix[6]
            output[2] = matrix[10]

# setTranslation

- A vector specifying the translation to set.
- A matrix to set the translation of.

Overwrites the translation of the matrix with the content of the given vector.

        setTranslation: (output, matrix) ->
            matrix[3] = output[0]
            matrix[7] = output[1]
            matrix[11] = output[2]

# setX

- A vector specifying the X axis vector to set.
- A matrix to set the X axis vector of.

Overwrites the X axis of the matrix with the content of the given vector.

        setX: (output, matrix) ->
            matrix[0] = output[0]
            matrix[4] = output[1]
            matrix[8] = output[2]

# setY

- A vector specifying the Y axis vector to set.
- A matrix to set the Y axis vector of.

Overwrites the Y axis of the matrix with the content of the given vector.

        setY: (output, matrix) ->
            matrix[1] = output[0]
            matrix[5] = output[1]
            matrix[9] = output[2]

# setZ

- A vector specifying the Z axis vector to set.
- A matrix to set the Z axis vector of.

Overwrites the Z axis of the matrix with the content of the given vector.

        setZ: (output, matrix) ->
            matrix[2] = output[0]
            matrix[6] = output[1]
            matrix[10] = output[2]

# interpolate

- An input matrix to interpolate from.
- An input matrix to interpolate to.
- A number specifying how far along to interpolate; "0" is "from" and "1" is
  "to".
- An output matrix.

Attempts to perform a somewhat crude interpolation between the two matrices
which is not very linear.  Good enough for smoothing over small changes.
Prioritizes the Z and Y axes over the X axis when ensuring orthogonal.

        interpolate: (from, to, alpha, output) ->
            module.exports.copy from, fromTemp
            module.exports.copy to, toTemp
            module.exports.identity output
            module.exports.getTranslation fromTemp, tempVectorFrom
            module.exports.getTranslation toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            module.exports.setTranslation tempVector, output

            module.exports.getX fromTemp, tempVectorFrom
            module.exports.getX toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            vector.normalize tempVector, tempVectorX, true

            module.exports.getY fromTemp, tempVectorFrom
            module.exports.getY toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVectorY

            vector.cross tempVectorX, tempVectorY, tempVectorZ
            vector.normalize tempVectorZ, tempVectorZ
            vector.cross tempVectorZ, tempVectorX, tempVectorY
            vector.normalize tempVectorY, tempVectorY

            module.exports.setX tempVectorX, output
            module.exports.setY tempVectorY, output
            module.exports.setZ tempVectorZ, output
            return

# invert

- An input matrix to invert.
- An output matrix to write to.

Attempts to calculate the inverse of a matrix by negating its translation and
transposing its X, Y and Z axes.  Will not work if any scaling has been applied.

        invert: (input, output) ->
            module.exports.copy input, fromTemp
            module.exports.getX fromTemp, tempVectorX
            module.exports.getY fromTemp, tempVectorY
            module.exports.getZ fromTemp, tempVectorZ
            module.exports.getTranslation fromTemp, tempVector
            output[0] = fromTemp[0]
            output[1] = fromTemp[4]
            output[2] = fromTemp[8]
            output[3] = -vector.dot tempVector, tempVectorX

            output[4] = fromTemp[1]
            output[5] = fromTemp[5]
            output[6] = fromTemp[9]
            output[7] = -vector.dot tempVector, tempVectorY

            output[8] = fromTemp[2]
            output[9] = fromTemp[6]
            output[10] = fromTemp[10]
            output[11] = -vector.dot tempVector, tempVectorZ

            output[12] = 0
            output[13] = 0
            output[14] = 0
            output[15] = 1

            return

    module.exports.identity temp1
    module.exports.identity temp2
    for mat in rotationTemp
        module.exports.identity mat

Matrices are arrays of 16 numbers forming a 4x4 matrix.

    temp1 = []
    temp2 = []
    rotationTemp = []
    tempVector = []
    tempVectorFrom = []
    tempVectorTo = []
    fromTemp = []
    toTemp = []
    tempVectorX = []
    tempVectorY = []
    tempVectorZ = []

    makeRotate = (axis1, axis2, axis3, axis4) ->
        temp3 = []
        rotationTemp.push temp3
        (radians, output, local) ->
            sin = Math.sin radians
            cos = Math.cos radians
            temp3[axis1] = cos
            temp3[axis2] = -sin
            temp3[axis3] = sin
            temp3[axis4] = cos
            if local
                module.exports.multiply temp3, output, output
            else
                module.exports.multiply output, temp3, output
            return

    vector = require "./vector.litcoffee"

    module.exports =

Given a matrix, calling the "identity" property writes the identity matrix to
it.

        identity: (output) ->
            for row in [0...4]
                for column in [0...4]
                    output[row * 4 + column] = if row is column then 1 else 0
            return

Given two matrices, calling the "copy" property copies every component from the
first to the second.

        copy: (input, output) ->
            output[index] = value for value, index in input
            return

Given three matrices, calling the "multiply" property multiplies the first two
together and writes the result to the third.

        multiply: (a, b, output) ->
            module.exports.copy a, temp1
            module.exports.copy b, temp2

            for row in [0...4]
                for column in [0...4]
                    temp = 0
                    for component in [0...4]
                        temp += temp1[component * 4 + column] * temp2[row * 4 + component]
                    output[row * 4 + column] = temp
            return

Given a number of radians and a matrix, calling the "rotateX" property modifies
the matrix to have been rotated by that number of radians about the X axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateX: makeRotate 5, 6, 9, 10

Given a number of radians and a matrix, calling the "rotateY" property modifies
the matrix to have been rotated by that number of radians about the Y axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateY: makeRotate 0, 2, 8, 10

Given a number of radians and a matrix, calling the "rotateZ" property modifies
the matrix to have been rotated by that number of radians about the Z axis.
If the third parameter is truthy, the rotation is applied in local rather than
global space.

        rotateZ: makeRotate 0, 1, 4, 5

Given a vector specifying the scaling factor on each axis and a matrix, calling
the "scale" property scales the matrix by those scaling factors.

        scale: (vector, output) ->
            output[index] *= vector[0] for index in [0...4]
            output[index] *= vector[1] for index in [4...8]
            output[index] *= vector[2] for index in [8...12]
            return

# translate

- A vector to translate by.
- A matrix to translate.
- When truthy, the translation is applied in local space, otherwise it is
  applied in global space.

        translate: (v, output, local) ->
            if local
                tempVectorX[0] = output[0]
                tempVectorX[1] = output[1]
                tempVectorX[2] = output[2]

                tempVectorY[0] = output[4]
                tempVectorY[1] = output[5]
                tempVectorY[2] = output[6]

                tempVectorZ[0] = output[8]
                tempVectorZ[1] = output[9]
                tempVectorZ[2] = output[10]

                tempVector[0] = vector.dot tempVectorX, v
                tempVector[1] = vector.dot tempVectorY, v
                tempVector[2] = vector.dot tempVectorZ, v
                module.exports.translate tempVector, output
            else
                output[3] += v[0]
                output[7] += v[1]
                output[11] += v[2]
            return

Given a matrix, X, Y, Z and W values (defaulting to 0, 0, 0 and 1 respectively
if not given), calling the "apply" property returns an array of four numbers
representing the transformed vector.

        apply: (matrix, x, y, z, w) ->
            if x is undefined then x = 0
            if y is undefined then y = 0
            if z is undefined then z = 0
            if w is undefined then w = 1

            [
                x * matrix[0] + y * matrix[1] + z * matrix[2] + w * matrix[3]
                x * matrix[4] + y * matrix[5] + z * matrix[6] + w * matrix[7]
                x * matrix[8] + y * matrix[9] + z * matrix[10] + w * matrix[11]
                x * matrix[12] + y * matrix[13] + z * matrix[14] + w * matrix[15]
            ]

Given a matrix, input vector and output vector, calling the "applyToVector"
property writes the input vector transformed by the matrix to the output vector.

        applyToVector: (matrix, input, output) ->
            vector.copy input, tempVector
            output[0] = tempVector[0] * matrix[0] + tempVector[1] * matrix[1] + tempVector[2] * matrix[2] + matrix[3]
            output[1] = tempVector[0] * matrix[4] + tempVector[1] * matrix[5] + tempVector[2] * matrix[6] + matrix[7]
            output[2] = tempVector[0] * matrix[8] + tempVector[1] * matrix[9] + tempVector[2] * matrix[10] + matrix[11]
            return

Given a matrix and output vector, calling the "getTranslation" property writes
the translation applied by the matrix to the output vector.

        getTranslation: (matrix, output) ->
            output[0] = matrix[3]
            output[1] = matrix[7]
            output[2] = matrix[11]

Given a matrix and output vector, calling the "getX" property writes the vector
of the matrix's X axis (a scaled normal) to the output vector.

        getX: (matrix, output) ->
            output[0] = matrix[0]
            output[1] = matrix[4]
            output[2] = matrix[8]

Given a matrix and output vector, calling the "getY" property writes the vector
of the matrix's Y axis (a scaled normal) to the output vector.

        getY: (matrix, output) ->
            output[0] = matrix[1]
            output[1] = matrix[5]
            output[2] = matrix[9]

Given a matrix and output vector, calling the "getZ" property writes the vector
of the matrix's Z axis (a scaled normal) to the output vector.

        getZ: (matrix, output) ->
            output[0] = matrix[2]
            output[1] = matrix[6]
            output[2] = matrix[10]

# setTranslation

- A vector specifying the translation to set.
- A matrix to set the translation of.

Overwrites the translation of the matrix with the content of the given vector.

        setTranslation: (output, matrix) ->
            matrix[3] = output[0]
            matrix[7] = output[1]
            matrix[11] = output[2]

# setX

- A vector specifying the X axis vector to set.
- A matrix to set the X axis vector of.

Overwrites the X axis of the matrix with the content of the given vector.

        setX: (output, matrix) ->
            matrix[0] = output[0]
            matrix[4] = output[1]
            matrix[8] = output[2]

# setY

- A vector specifying the Y axis vector to set.
- A matrix to set the Y axis vector of.

Overwrites the Y axis of the matrix with the content of the given vector.

        setY: (output, matrix) ->
            matrix[1] = output[0]
            matrix[5] = output[1]
            matrix[9] = output[2]

# setZ

- A vector specifying the Z axis vector to set.
- A matrix to set the Z axis vector of.

Overwrites the Z axis of the matrix with the content of the given vector.

        setZ: (output, matrix) ->
            matrix[2] = output[0]
            matrix[6] = output[1]
            matrix[10] = output[2]

# interpolate

- An input matrix to interpolate from.
- An input matrix to interpolate to.
- A number specifying how far along to interpolate; "0" is "from" and "1" is
  "to".
- An output matrix.

Attempts to perform a somewhat crude interpolation between the two matrices
which is not very linear.  Good enough for smoothing over small changes.
Prioritizes the Z and Y axes over the X axis when ensuring orthogonal.

        interpolate: (from, to, alpha, output) ->
            module.exports.copy from, fromTemp
            module.exports.copy to, toTemp
            module.exports.identity output
            module.exports.getTranslation fromTemp, tempVectorFrom
            module.exports.getTranslation toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            module.exports.setTranslation tempVector, output

            module.exports.getX fromTemp, tempVectorFrom
            module.exports.getX toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVector
            vector.normalize tempVector, tempVectorX, true

            module.exports.getY fromTemp, tempVectorFrom
            module.exports.getY toTemp, tempVectorTo
            vector.interpolate tempVectorFrom, tempVectorTo, alpha, tempVectorY

            vector.cross tempVectorX, tempVectorY, tempVectorZ
            vector.normalize tempVectorZ, tempVectorZ
            vector.cross tempVectorZ, tempVectorX, tempVectorY
            vector.normalize tempVectorY, tempVectorY

            module.exports.setX tempVectorX, output
            module.exports.setY tempVectorY, output
            module.exports.setZ tempVectorZ, output
            return

# invert

- An input matrix to invert.
- An output matrix to write to.

Attempts to calculate the inverse of a matrix by negating its translation and
transposing its X, Y and Z axes.  Will not work if any scaling has been applied.

        invert: (input, output) ->
            module.exports.copy input, fromTemp
            module.exports.getX fromTemp, tempVectorX
            module.exports.getY fromTemp, tempVectorY
            module.exports.getZ fromTemp, tempVectorZ
            module.exports.getTranslation fromTemp, tempVector
            output[0] = input[0]
            output[1] = input[4]
            output[2] = input[8]
            output[3] = -vector.dot tempVector, tempVectorX

            output[4] = input[1]
            output[5] = input[5]
            output[6] = input[9]
            output[7] = -vector.dot tempVector, tempVectorY

            output[8] = input[2]
            output[9] = input[6]
            output[10] = input[10]
            output[11] = -vector.dot tempVector, tempVectorZ

            output[12] = 0
            output[13] = 0
            output[14] = 0
            output[15] = 1

            return

    module.exports.identity temp1
    module.exports.identity temp2
    for mat in rotationTemp
        module.exports.identity mat


Add 404 route handling

Add 404 route handling

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketUrl: "https://s3-eu-west-1.amazonaws.com/#{process.env.AWS_BUCKET_NAME}/"
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      if not req.get('Origin') or not (req.get('Origin') in origins)
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      console.log "Recieved #{Object.keys(req.files).length} files"

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension not in ['jpg', 'jpeg', 'png', 'gif', 'tiff']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use (req, res, next) ->
      res.status(404).json message: 'Not Found'

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketUrl: "https://s3-eu-west-1.amazonaws.com/#{process.env.AWS_BUCKET_NAME}/"
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      if not req.get('Origin') or not (req.get('Origin') in origins)
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      console.log "Recieved #{Object.keys(req.files).length} files"

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension not in ['jpg', 'jpeg', 'png', 'gif', 'tiff']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app


⚠ fix markdown

⚠ fix markdown

# Weya.Base.js

    @Weya = {} unless @Weya?
    Weya = @Weya

    Weya.ANALYTICS = {}

    WRAP = (className, methodName, func) ->
     wrap = ->
      args = (typeof arg for arg in arguments)
      args = args.join ','
      c = Weya.ANALYTICS[className] ?= {}
      c = c[methodName] ?= {}
      ret = func.apply this, arguments
      signature = "(#{args}) -> #{typeof ret}"
      c[signature] ?= 0
      c[signature]++
      return ret

## Weya.Base
Introduces class level function initialize and include.

    class Base
     _initialize: []
     on: {}

     _extended: true

     _debug: false
     _analytics: true

     @weyaDebug: ->
      @::_debug = true

     @weyaAnalytics: (name) ->
      @::_analytics = true

      return if not @::_debug

      for k, v of this.prototype
       continue if ((typeof v) isnt 'function')
       this.prototype[k] = WRAP name, k, v

Extend Events

     @extend: ->
      events = @::on
      @::on = {}
      @::on[k] = v for k, v of events
      @::_extended = true
      @::_analytics = false

Add event listeners

     @listen: (name, func) ->
      @::on[name] = func

Getter

     @get: (name, func) ->
      @::__defineGetter__ name, func

Setter

     @set: (name, func) ->
      @::__defineSetter__ name, func

     constructor: ->
      @_init.apply this, arguments

#### Register initialize functions.
All initializer funcitons in subclasses will be called with the constructor
arguments.

     @initialize: (func) ->
      #if not @::_extended
      # throw new Error 'Class not extended'

      @::_extended = false

      @::_initialize = @::_initialize.slice()
      @::_initialize.push func

     _init: ->
      if not @_analytics
       throw new Error 'Class analytics not called'

      for init in @_initialize
       init.apply this, arguments

      return

#### Include objects.
You can include objects by registering them with @include. This tries to
solve the problem of single inheritence.

     @include: (obj) ->
      for k, v of obj
       switch k
        when 'initialize'
         @::_initialize.push v
        when 'on'
         for event, listener of v
          @::on[event] = listener
        else
         @prototype[k] = v

     @initialize ->
      events = @on
      @on = {}
      for k, v of events
       @on[k] = v.bind this

    Weya.Base = Base

    if module?
     module.exports = Weya.Base

#Weya.Base.js

    @Weya = {} unless @Weya?
    Weya = @Weya

    Weya.ANALYTICS = {}

    WRAP = (className, methodName, func) ->
     wrap = ->
      args = (typeof arg for arg in arguments)
      args = args.join ','
      c = Weya.ANALYTICS[className] ?= {}
      c = c[methodName] ?= {}
      ret = func.apply this, arguments
      signature = "(#{args}) -> #{typeof ret}"
      c[signature] ?= 0
      c[signature]++
      return ret

##Weya.Base
Introduces class level function initialize and include.

    class Base
     _initialize: []
     on: {}

     _extended: true

     _debug: false
     _analytics: true

     @weyaDebug: ->
      @::_debug = true

     @weyaAnalytics: (name) ->
      @::_analytics = true

      return if not @::_debug

      for k, v of this.prototype
       continue if ((typeof v) isnt 'function')
       this.prototype[k] = WRAP name, k, v

Extend Events

     @extend: ->
      events = @::on
      @::on = {}
      @::on[k] = v for k, v of events
      @::_extended = true
      @::_analytics = false

Add event listeners

     @listen: (name, func) ->
      @::on[name] = func

Getter

     @get: (name, func) ->
      @::__defineGetter__ name, func

Setter

     @set: (name, func) ->
      @::__defineSetter__ name, func

     constructor: ->
      @_init.apply this, arguments

####Register initialize functions.
All initializer funcitons in subclasses will be called with the constructor
arguments.

     @initialize: (func) ->
      #if not @::_extended
      # throw new Error 'Class not extended'

      @::_extended = false

      @::_initialize = @::_initialize.slice()
      @::_initialize.push func

     _init: ->
      if not @_analytics
       throw new Error 'Class analytics not called'

      for init in @_initialize
       init.apply this, arguments

      return

####Include objects.
You can include objects by registering them with @include. This tries to
solve the problem of single inheritence.

     @include: (obj) ->
      for k, v of obj
       switch k
        when 'initialize'
         @::_initialize.push v
        when 'on'
         for event, listener of v
          @::on[event] = listener
        else
         @prototype[k] = v

     @initialize ->
      events = @on
      @on = {}
      for k, v of events
       @on[k] = v.bind this

    Weya.Base = Base

    if module?
     module.exports = Weya.Base


Added some rendering pipeline options

Added some rendering pipeline options

The three options allow for easy debugging

    module.exports = require 'yargs'
      .usage 'Usage: $0 [options] levelname anotherlevelname yetanotherlevelname ...'
      .example '$0',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -vvvvvvvv',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to verbosity level 8 (max)\n"
      .example '$0 -w 20 -h 20',
        "Creates a level with default row and column counts,
         the cells 20 units wide, 20 units high,
         expanded by the default multiplier,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -w 10 -h 10 -x 4',
        "Creates a level with default row and column counts,
         40 x 40 unit cells,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 lvl1 lvl2',
        "Creates two levels; named lvl1 and lvl2 -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 --levels one two three',
        "Creates three levels; named one, two, and three -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 -l10',
        "Creates ten auto-named levels -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .count 'verbosity'
      .alias 'v', 'verbosity'
      .describe 'v', 'Level of logging verbosity: 1 - 8'
      .alias 'r', 'rows'
      .describe 'r', 'Number of rows for map'
      .alias 'c', 'columns'
      .describe 'c', 'Number of columns for map'
      .alias 'w', 'width'
      .describe 'w', 'Width of a grid cell'
      .alias 'h', 'height'
      .describe 'h', 'Height of a grid cell'
      .alias 'x', 'multiplier'
      .describe 'x', 'Increase cell size by x times'
      .number 'l'
      .describe 'l', 'Number of auto-named levels to create'
      .array 'levels'
      .describe 'levels', 'Array of named levels to create'
      .array 'pipeline'
      .alias 'p', 'pipeline'
      .describe 'p', 'The steps of the render pipleline'
      .string 'conf'
      .describe 'conf', 'Absolute path to config file'
      .string 'block.fill_color'
      .describe 'block.fill_color', 'Path block color. Can be an html color name or hex value'
      .string 'ground.fill_color'
      .describe 'ground.fill_color', 'Ground block color. Can be an html color name or hex value'
      .string 'step_count.text.align'
      .choices 'step_count.text.align', [ 'left', 'center', 'right' ]
      .string 'step_count.text.color'
      .describe 'step_count.text.color', 'Can be either html color names or hex values'
      .number 'ground.segments'
      .number 'ground.max_height_diff'
      .number 'wall.width'
      .string 'wall.color'
      .describe 'wall.color', 'Can be either html color names or hex values'
      .conflicts 'levels', 'l'
      .help 'help'
      .default
        verbosity:  3
        rows:       15
        columns:    50
        width:      24
        height:     24
        multiplier: 4
        # pipeline:   [ 'json_blocks', 'json_ground', 'json_walls' ]
        # pipeline:   [ 'png_blocks', 'png_walls', 'png_ground', 'png_step_count' ]
        pipeline: [
          [ 'json_blocks', 'json_ground', 'json_walls' ]
          [ 'png_blocks',  'png_ground',  'png_walls', 'png_roof', 'png_step_count' ]
        ]
        block:
          fill_color: 'white'
        ground:
          fill_color:     '#888'
          segments:        24
          max_height_diff: 4
        step_count:
          text:
            align: 'center'
            color: 'black'
        wall:
          width: 1
          color: '#666'
          segments: 24
      .epilogue '© Bryan Maynard 2016'
      .wrap 120
      .argv

    module.exports = require 'yargs'
      .usage 'Usage: $0 [options] levelname anotherlevelname yetanotherlevelname ...'
      .example '$0',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -vvvvvvvv',
        "Creates a level with default row and column counts,
         the default size and multiplier for each cell,
         an auto-generated name,
         and logging set to verbosity level 8 (max)\n"
      .example '$0 -w 20 -h 20',
        "Creates a level with default row and column counts,
         the cells 20 units wide, 20 units high,
         expanded by the default multiplier,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 -w 10 -h 10 -x 4',
        "Creates a level with default row and column counts,
         40 x 40 unit cells,
         an auto-generated name,
         and logging set to default verbosity\n"
      .example '$0 lvl1 lvl2',
        "Creates two levels; named lvl1 and lvl2 -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 --levels one two three',
        "Creates three levels; named one, two, and three -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .example '$0 -l10',
        "Creates ten auto-named levels -
         each with default row and column counts,
         the default size and multiplier for each cell,
         and logging set to default verbosity\n"
      .count 'verbosity'
      .alias 'v', 'verbosity'
      .describe 'v', 'Level of logging verbosity: 1 - 8'
      .alias 'r', 'rows'
      .describe 'r', 'Number of rows for map'
      .alias 'c', 'columns'
      .describe 'c', 'Number of columns for map'
      .alias 'w', 'width'
      .describe 'w', 'Width of a grid cell'
      .alias 'h', 'height'
      .describe 'h', 'Height of a grid cell'
      .alias 'x', 'multiplier'
      .describe 'x', 'Increase cell size by x times'
      .number 'l'
      .describe 'l', 'Number of auto-named levels to create'
      .array 'levels'
      .describe 'levels', 'Array of named levels to create'
      .array 'pipeline'
      .alias 'p', 'pipeline'
      .describe 'p', 'The steps of the render pipleline'
      .string 'conf'
      .describe 'conf', 'Absolute path to config file'
      .string 'block.fill_color'
      .describe 'block.fill_color', 'Path block color. Can be an html color name or hex value'
      .string 'ground.fill_color'
      .describe 'ground.fill_color', 'Ground block color. Can be an html color name or hex value'
      .string 'step_count.text.align'
      .choices 'step_count.text.align', [ 'left', 'center', 'right' ]
      .string 'step_count.text.color'
      .describe 'step_count.text.color', 'Can be either html color names or hex values'
      .number 'ground.segments'
      .number 'ground.max_height_diff'
      .number 'wall.width'
      .string 'wall.color'
      .describe 'wall.color', 'Can be either html color names or hex values'
      .conflicts 'levels', 'l'
      .help 'help'
      .default
        verbosity:  3
        rows:       15
        columns:    50
        width:      24
        height:     24
        multiplier: 4
        pipeline:   [ 'png_blocks', 'png_walls', 'png_grounder', 'png_step_count' ]
        block:
          fill_color: 'white'
        ground:
          fill_color:     '#888'
          segments:        24
          max_height_diff: 4
        step_count:
          text:
            align: 'center'
            color: 'black'
        wall:
          width: 1
          color: '#666'
          segments: 24
      .epilogue '© Bryan Maynard 2016'
      .wrap 120
      .argv


Improved documentation of the plane module.

# plane

A plane is an object containing:

- normal: A vector specifying the facing direction of the plane.
- distance: A number specifying how far from 0, 0, 0 along the normal the plane
            is.

    vector = require "./vector.litcoffee"
    tempA = []
    tempB = []

## fromTriangle

- A vector specifying the location of the first vertex.
- A vector specifying the location of the second vertex.
- A vector specifying the location of the third vertex.
- An existing object to populate, else, falsy.

The populated object is returned.

    fromTriangle = (a, b, c, output) ->
        output = output or {}
        output.normal = output.normal or []
        vector.subtract.vector a, b, tempA
        vector.subtract.vector a, c, tempB
        vector.cross tempB, tempA, output.normal
        vector.normalize output.normal, output.normal
        output.distance = vector.dot output.normal, a
        output

## distance

- A plane.
- A vector.

Returns the distance between the plane and the vector.  Negative when behind the
plane.

    distance = (plane, input) -> (vector.dot plane.normal, input) - plane.distance

## project

- A plane.
- An input vector.
- An output vector.

Projects the input vector onto the surface of the plane, travelling along its
normal to find the closest point, and writes that point to the output vector.

    project = (plane, input, output) ->
        dist = distance plane, input
        vector.multiply.scalarBy dist, plane.normal, tempA
        vector.subtract.vector input, tempA, output
        return

    module.exports = {
        fromTriangle
        distance
        project
    }

A plane is an object containing:

- normal: A vector specifying the facing direction of the plane.
- distance: A number specifying how far from 0, 0, 0 along the normal the plane
            is.

Exports an object.

    vector = require "./vector.litcoffee"
    tempA = []
    tempB = []

Call the "fromTriangle" property with three input vectors forming a clockwise
triangle and an output object to create a plane on which those three vectors
lie.  If the output object is undefined, an empty one is created.  The output
object is returned.

    fromTriangle = (a, b, c, output) ->
        output = output or {}
        output.normal = output.normal or []
        vector.subtract.vector a, b, tempA
        vector.subtract.vector a, c, tempB
        vector.cross tempB, tempA, output.normal
        vector.normalize output.normal, output.normal
        output.distance = vector.dot output.normal, a
        output

Call the "distance" property with a plane and a vector.  The distance between
the plane and vector is returned.  If the vector is behind the plane, the
distance is negative.

    distance = (plane, input) -> (vector.dot plane.normal, input) - plane.distance

Call the "project" property with a plane, input vector and output vector to
write the nearest point to the input vector on the plane to the output vector.

    project = (plane, input, output) ->
        dist = distance plane, input
        vector.multiply.scalarBy dist, plane.normal, tempA
        vector.subtract.vector input, tempA, output
        return

    module.exports = {
        fromTriangle
        distance
        project
    }


value to string fix

value to string fix

Copyright 2014 - 2015
Author: Varuna Jayasiri http://blog.varunajayasiri.com

#Value

    Mod.require 'Models.Properties',
     'Models.Property.Base'
     'Weya.Base'
     'Weya'
     (PROPERTIES, Base, WeyaBase, Weya) ->

Class

      class Value extends Base
       @extend()

       propertyType: 'value'

       @default 'value', (str, stack) ->
        if (typeof str) isnt 'string'
         throw new Error "Exected string: #{typeof str}, #{str}"
        return str

       @default 'string', (value, stack) -> "#{value}"

       @default 'rows', 1
       @default 'columns', 20

       @default 'valid', (str, stack) ->
        if (typeof str) isnt 'string'
         return false
        else
         return true

       @default 'search', (str, stack) -> null

       @default 'default', -> ''

       @default 'isDefault', (value, stack) ->
        value is @schema.default()

       parse: (data, stack) ->
        r = super data, stack
        return r unless r is true
        if not @schema.valid data, stack
         return @error 'invalid'

        return {
         score: 1
         errors: []
         value: @schema.value data, stack
        }

       toJSON: (value, stack) -> value
       toJSONFull: (value, stack) -> value

       edit: (elem, value, onChanged, stack) ->
        new Edit this, elem, value, onChanged, stack

Edit

      class Edit extends WeyaBase
       @extend()

       @initialize (property, elem, value, onChanged, stack) ->
        @property = property
        @elems =
         parent: elem
        @value = value
        @onChanged = onChanged
        @stack = stack
        @render()

       render: ->
        schema = @property.schema
        width = 2 + Math.round schema.columns * 7.25
        Weya elem: @elems.parent, context: this, ->
         if schema.rows is 1
          @$.elems.input = @input '.value',
           type: 'text'
           placeholder: @$.property._name
           style:
            width: "#{width}px"
         else
          @$.elems.input = @textarea '.value',
           rows: schema.rows
           columns: schema.columns
           style:
            width: "#{width}px"
            height: "#{Math.round schema.rows * 18}px"

         @$.elems.search = @div '.search',
          style:
           display: 'none'
           width: "#{width}px"

        @elems.input.value = schema.string @value, @stack
        @elems.input.addEventListener "input", @on.change
        @elems.input.addEventListener "focus", @on.focus
        @elems.input.addEventListener "blur", @on.blur
        @elems.search.addEventListener 'click', @on.searchClick
        @change()

       search: ->
        value = @elems.input.value
        results = @property.schema.search.call @property, value, @stack
        return if not results?
        return if not Array.isArray results

        if results.length is 0
         @elems.search.style.display = 'none'
         return

        @elems.search.style.display = 'block'
        @elems.search.innerHTML = ''
        Weya elem: @elems.search, ->
         for r, i in results
          break if i > 10
          e = @div r
          e._result = r

       @listen 'searchClick', (e) ->
        n = e.target
        result = null
        while n? and n isnt @elems.search
         if n._result
          result = n._result
          break
         n = n.parentNode

        return if not result?
        @elems.input.value = result
        @elems.search.style.display = 'none'
        @change()

       @listen 'focus', (e) -> @search()
       @listen 'blur', (e) ->
        setTimeout =>
         @elems.search.style.display = 'none'
        , 400

       @listen 'change', (e) ->
        @search()
        @change()

       change: ->
        value = @elems.input.value
        if not @property.schema.valid.call @property, value, @stack
         @elems.input.classList.add 'invalid'
        else
         @elems.input.classList.remove 'invalid'
         value = @property.schema.value.call this, value, @stack
         @onChanged value, true

      PROPERTIES.register 'value', Value

Copyright 2014 - 2015
Author: Varuna Jayasiri http://blog.varunajayasiri.com

#Value

    Mod.require 'Models.Properties',
     'Models.Property.Base'
     'Weya.Base'
     'Weya'
     (PROPERTIES, Base, WeyaBase, Weya) ->

Class

      class Value extends Base
       @extend()

       propertyType: 'value'

       @default 'value', (str, stack) ->
        if (typeof str) isnt 'string'
         throw new Error "Exected string: #{typeof str}, #{str}"
        return str

       @default 'string', (value, stack) -> "#{str}"

       @default 'rows', 1
       @default 'columns', 20

       @default 'valid', (str, stack) ->
        if (typeof str) isnt 'string'
         return false
        else
         return true

       @default 'search', (str, stack) -> null

       @default 'default', -> ''

       @default 'isDefault', (value, stack) ->
        value is @schema.default()

       parse: (data, stack) ->
        r = super data, stack
        return r unless r is true
        if not @schema.valid data, stack
         return @error 'invalid'

        return {
         score: 1
         errors: []
         value: @schema.value data, stack
        }

       toJSON: (value, stack) -> value
       toJSONFull: (value, stack) -> value

       edit: (elem, value, onChanged, stack) ->
        new Edit this, elem, value, onChanged, stack

Edit

      class Edit extends WeyaBase
       @extend()

       @initialize (property, elem, value, onChanged, stack) ->
        @property = property
        @elems =
         parent: elem
        @value = value
        @onChanged = onChanged
        @stack = stack
        @render()

       render: ->
        schema = @property.schema
        width = 2 + Math.round schema.columns * 7.25
        Weya elem: @elems.parent, context: this, ->
         if schema.rows is 1
          @$.elems.input = @input '.value',
           type: 'text'
           placeholder: @$.property._name
           style:
            width: "#{width}px"
         else
          @$.elems.input = @textarea '.value',
           rows: schema.rows
           columns: schema.columns
           style:
            width: "#{width}px"
            height: "#{Math.round schema.rows * 18}px"

         @$.elems.search = @div '.search',
          style:
           display: 'none'
           width: "#{width}px"

        @elems.input.value = schema.string @value, @stack
        @elems.input.addEventListener "input", @on.change
        @elems.input.addEventListener "focus", @on.focus
        @elems.input.addEventListener "blur", @on.blur
        @elems.search.addEventListener 'click', @on.searchClick
        @change()

       search: ->
        value = @elems.input.value
        results = @property.schema.search.call @property, value, @stack
        return if not results?
        return if not Array.isArray results

        if results.length is 0
         @elems.search.style.display = 'none'
         return

        @elems.search.style.display = 'block'
        @elems.search.innerHTML = ''
        Weya elem: @elems.search, ->
         for r, i in results
          break if i > 10
          e = @div r
          e._result = r

       @listen 'searchClick', (e) ->
        n = e.target
        result = null
        while n? and n isnt @elems.search
         if n._result
          result = n._result
          break
         n = n.parentNode

        return if not result?
        @elems.input.value = result
        @elems.search.style.display = 'none'
        @change()

       @listen 'focus', (e) -> @search()
       @listen 'blur', (e) ->
        setTimeout =>
         @elems.search.style.display = 'none'
        , 400

       @listen 'change', (e) ->
        @search()
        @change()

       change: ->
        value = @elems.input.value
        if not @property.schema.valid.call @property, value, @stack
         @elems.input.classList.add 'invalid'
        else
         @elems.input.classList.remove 'invalid'
         value = @property.schema.value.call this, value, @stack
         @onChanged value, true

      PROPERTIES.register 'value', Value


Fix undefined tilbyder name in error mmesasge

    raven       = require 'raven'
    sentry      = require './db/sentry'
    express     = require 'express'

    auth        = require './helper/auth'

    system      = require './system'
    collection  = require './collection'
    document    = require './document'

## Init

    app = express()

### Authentication

This routine is called for all request to the API. It is reponsible for
authenticating the user by validating the `api\_key`. It then sets some request
session variables so they become accessible throughout the entire system during
the rquest.

    app.use '/', (req, res, next) ->
      return next() if req.originalUrl.substr(0, 17) is '/CloudHealthCheck'

      auth.check req.query.api_key, (err, user) ->
        if user
          res.set 'X-RateLimit-Limit', user.limit
          res.set 'X-RateLimit-Remaining', user.remaining
          res.set 'X-RateLimit-Reset', user.reset

        req.user = user

        return next err if err

        next()

### Configuration

    app.use(express.favicon())
    app.use(express.logger(':date :remote-addr - :method :url :status :res[content-length] - :response-time ms')) if not process.env.SILENT
    app.set('json spaces', 0) if app.get('env') isnt 'testing'
    app.use(express.compress())
    app.use(express.json())
    app.disable('x-powered-by')
    app.set 'port', process.env.PORT_WWW or 8080
    app.use(app.router)

### Error handling

Before handling the error ours self make sure that it is propperly logged in
Sentry by using the express/connect middleware.

    app.use raven.middleware.express sentry

All errors passed to `next` or exceptions ends up here. We set the status code
to `500` if it is not already defined in the `Error` object. We then print the
error mesage and stack trace to the console for debug purposes.

Log 401 Unauthorized (warning) and 403 Forbidden (notice) errors to Sentry to
enhance debugging and oversight as Nasjonal Turbase gets more used.

Before returning a response to the user the request method is check. HEAD
requests shall not contain any body – this applies for errors as well.

    app.use (err, req, res, next) ->
      res.status err.status or 500

      if res.statusCode is 401
        sentry.captureMessage "Invalid API-key #{req.query.api_key}",
          level: 'warning'
          extra: sentry.parseRequest req, user: req.user

      if res.statusCode is 403
        sentry.captureMessage "Rate limit exceeded for #{req.user.tilbyder}",
          level: 'notice'
          extra: sentry.parseRequest req, user: req.user

      if res.statusCode >= 500
        console.error err.message
        console.error err.stack

      return res.end() if req.method is 'HEAD'
      return res.json message: err.message or 'Ukjent feil'

This the fmous 404 Not Found handler. If no route configuration for the request
is found, it ends up here. We don't do much fancy about it – just a standard
error message and HTTP status code.

    app.use (req, res) -> res.json 404, message: "Resurs ikke funnet"

## GET /

    app.get '/', (req, res) ->
      res.json message: 'Here be dragons'

## GET /CloudHealthCheck

> So...You’re seeing the dotCloud active health check looking to make sure that
> your service is up. There is no way for you to disable it, but you can prevent
> it and you can handle it [1]!

[1] [dotCloud](http://docs.dotcloud.com/tutorials/more/cloud-health-check/)

    app.all '/CloudHealthCheck', system.check

## GET /objekttyper

    app.get '/objekttyper', (req, res, next) ->
      res.json 200, ['turer', 'steder', 'områder', 'grupper', 'arrangementer', 'bilder']

## ALL /{collection}

    app.param 'collection', collection.param
    app.all '/:collection', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then collection.options req, res, next
        when 'HEAD', 'GET' then collection.get req, res, next
        when 'POST' then collection.post req, res, next
        else res.json 405, message: "HTTP Method #{req.method.toUpperCase()} Not Allowed"

## ALL /{collection}/{objectid}

    app.param 'objectid', document.param
    app.options '/:collection/:ojectid', document.options
    app.all '/:collection/:objectid', document.all, (req, res, next) ->
      switch req.method
        when 'HEAD', 'GET' then document.get req, res, next
        when 'PUT' then document.put req, res, next
        when 'PATCH' then document.patch req, res, next
        when 'DELETE' then document.delete req, res, next
        else res.json 405, message: "HTTP Method #{req.method.toUpperCase()} Not Allowed"

## Start

Ok, so if the server is running in stand-alone mode i.e. there is not
`module.parent` then continue with starting the databse and listening to a port.

    if not module.parent
      require('./db/redis')
      require('./db/mongo').once 'ready', ->
        console.log 'Database is open...'

        app.listen app.get('port'), ->
          console.log "Server is listening on port #{app.get('port')}"

However, if there is a `module.parent` don't do all the stuff above. This means
that there is some program that is including the server from it, e.g a test, and
hence it should not listen to a port for incomming connections and rather just
return the application instance so that we can do some testing on it.

    else
      module.exports = app

    raven       = require 'raven'
    sentry      = require './db/sentry'
    express     = require 'express'

    auth        = require './helper/auth'

    system      = require './system'
    collection  = require './collection'
    document    = require './document'

## Init

    app = express()

### Authentication

This routine is called for all request to the API. It is reponsible for
authenticating the user by validating the `api\_key`. It then sets some request
session variables so they become accessible throughout the entire system during
the rquest.

    app.use '/', (req, res, next) ->
      return next() if req.originalUrl.substr(0, 17) is '/CloudHealthCheck'

      auth.check req.query.api_key, (err, user) ->
        if user
          res.set 'X-RateLimit-Limit', user.limit
          res.set 'X-RateLimit-Remaining', user.remaining
          res.set 'X-RateLimit-Reset', user.reset

        req.user = user

        return next err if err

        next()

### Configuration

    app.use(express.favicon())
    app.use(express.logger(':date :remote-addr - :method :url :status :res[content-length] - :response-time ms')) if not process.env.SILENT
    app.set('json spaces', 0) if app.get('env') isnt 'testing'
    app.use(express.compress())
    app.use(express.json())
    app.disable('x-powered-by')
    app.set 'port', process.env.PORT_WWW or 8080
    app.use(app.router)

### Error handling

Before handling the error ours self make sure that it is propperly logged in
Sentry by using the express/connect middleware.

    app.use raven.middleware.express sentry

All errors passed to `next` or exceptions ends up here. We set the status code
to `500` if it is not already defined in the `Error` object. We then print the
error mesage and stack trace to the console for debug purposes.

Log 401 Unauthorized (warning) and 403 Forbidden (notice) errors to Sentry to
enhance debugging and oversight as Nasjonal Turbase gets more used.

Before returning a response to the user the request method is check. HEAD
requests shall not contain any body – this applies for errors as well.

    app.use (err, req, res, next) ->
      res.status err.status or 500

      if res.statusCode is 401
        sentry.captureMessage "Invalid API-key #{req.query.api_key}",
          level: 'warning'
          extra: sentry.parseRequest req, user: req.user

      if res.statusCode is 403
        sentry.captureMessage "Rate limit exceeded for #{req.tilbyder}",
          level: 'notice'
          extra: sentry.parseRequest req, user: req.user

      if res.statusCode >= 500
        console.error err.message
        console.error err.stack

      return res.end() if req.method is 'HEAD'
      return res.json message: err.message or 'Ukjent feil'

This the fmous 404 Not Found handler. If no route configuration for the request
is found, it ends up here. We don't do much fancy about it – just a standard
error message and HTTP status code.

    app.use (req, res) -> res.json 404, message: "Resurs ikke funnet"

## GET /

    app.get '/', (req, res) ->
      res.json message: 'Here be dragons'

## GET /CloudHealthCheck

> So...You’re seeing the dotCloud active health check looking to make sure that
> your service is up. There is no way for you to disable it, but you can prevent
> it and you can handle it [1]!

[1] [dotCloud](http://docs.dotcloud.com/tutorials/more/cloud-health-check/)

    app.all '/CloudHealthCheck', system.check

## GET /objekttyper

    app.get '/objekttyper', (req, res, next) ->
      res.json 200, ['turer', 'steder', 'områder', 'grupper', 'arrangementer', 'bilder']

## ALL /{collection}

    app.param 'collection', collection.param
    app.all '/:collection', (req, res, next) ->
      switch req.method
        when 'OPTIONS' then collection.options req, res, next
        when 'HEAD', 'GET' then collection.get req, res, next
        when 'POST' then collection.post req, res, next
        else res.json 405, message: "HTTP Method #{req.method.toUpperCase()} Not Allowed"

## ALL /{collection}/{objectid}

    app.param 'objectid', document.param
    app.options '/:collection/:ojectid', document.options
    app.all '/:collection/:objectid', document.all, (req, res, next) ->
      switch req.method
        when 'HEAD', 'GET' then document.get req, res, next
        when 'PUT' then document.put req, res, next
        when 'PATCH' then document.patch req, res, next
        when 'DELETE' then document.delete req, res, next
        else res.json 405, message: "HTTP Method #{req.method.toUpperCase()} Not Allowed"

## Start

Ok, so if the server is running in stand-alone mode i.e. there is not
`module.parent` then continue with starting the databse and listening to a port.

    if not module.parent
      require('./db/redis')
      require('./db/mongo').once 'ready', ->
        console.log 'Database is open...'

        app.listen app.get('port'), ->
          console.log "Server is listening on port #{app.get('port')}"

However, if there is a `module.parent` don't do all the stuff above. This means
that there is some program that is including the server from it, e.g a test, and
hence it should not listen to a port for incomming connections and rather just
return the application instance so that we can do some testing on it.

    else
      module.exports = app


lodash replaced pluck

lodash replaced pluck

# Rate limiter

*Limits the rate at which clients can do certain operations, like call RPC
routes.*

    pkgman = require 'pkgman'

    exports.SKIP = SKIP = {}

A limiter on a route is defined like:

```javascript

registrar.registerHook('shrubRpcRoutes', function() {

  var shrubLimiter = require 'shrub-limiter'
  var Limiter = shrubLimiter.Limiter;
  var LimiterMiddleware = shrubLimiter.LimiterMiddleware;

  var routes = []

  routes.push({

.    path: 'my-package/route',

.    middleware: [

.      ...

.      'shrub-villiany' // Include if limit infractions lead to eventual ban

.      new LimiterMiddleware(
.        limiterDefinitionObject
.      )

.      ...

.    ]

  });

  return routes;
});

```

<small>***NOTE:*** *Ignore the leading dots, they are a result of literate coffee
limitations.*</small>

Where `limiterDefinitionObject` above is defined as an object with the
following properties:

* `threshold`: The [threshold](./limiter#threshold) for this limiter.
* `message`: The message returned to the client when the threshold is
  passed.
* `ignoreKeys`: The
  [fingerprint keys](source/server/fingerprint) to ignore when
  determining the total limit.
* `villianyScore`: The score accumulated when this limit is crossed.

### LimiterMiddleware

    exports.LimiterMiddleware = class LimiterMiddleware

      constructor: (@config) ->

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubOrmCollections`.

      registrar.registerHook 'shrubOrmCollections', ->

        _ = require 'lodash'

        Limit =

          autoPK: false

          associations: [
            alias: 'scores'
          ]

          attributes:

## Limit#key

*The limiter key.*

            key:
              type: 'string'
              primaryKey: true

## Limit#scores

*Scores accrued for this limit.*

            scores:
              collection: 'shrub-limit-score'
              via: 'limit'

## Limit#accrue

* (Number) `score` - The numeric score to accrue.

*Accrue a score for this limit.*

            accrue: (score) ->
              @scores.add score: score

              return this

## Limit#passed

* (Number) `threshold` - The threshold duration in seconds.

*Check whether a limit has passed the time threshold.*

            passed: (threshold) -> 0 >= @ttl threshold

## Limit#reset

*Reset scores and created time.*

            reset: ->
              @scores.remove id for id in _.map @scores, 'id'
              @createdAt = new Date()

              return this

## Limit#reset

*Get the sum of all scores for this limit.*

            score: ->
              _.map(@scores, 'score').reduce ((l, r) -> l + r), 0

## Limit#ttl

* (Number) `threshold` - The threshold duration in seconds.

*Get the current time-to-live for this limit.*

            ttl: (threshold) ->
              diff = (Date.now() - @createdAt.getTime()) / 1000
              Math.ceil threshold - diff

        LimitScore =

          attributes:

            score: 'integer'

            limit: model: 'shrub-limit'

        'shrub-limit': Limit
        'shrub-limit-score': LimitScore

#### Implements hook `shrubRpcRoutesAlter`.

Allow RPC routes definitions to specify rate limiters.

      registrar.registerHook 'shrubRpcRoutesAlter', (routes) ->

        Promise = require 'bluebird'
        moment = require 'moment'

        errors = require 'errors'

Check all routes' middleware for limiter definitions.

        Object.keys(routes).forEach (path) ->
          route = routes[path]

          Fingerprint = require 'fingerprint'

          for fn, index in route.middleware
            continue unless fn instanceof exports.LimiterMiddleware

            route.limiter = fn.config

Create a limiter based on the threshold defined.

            route.limiter.instance = new Limiter(
              "rpc://#{path}", route.limiter.threshold
            )

Set defaults.

            route.limiter.excludedKeys ?= []
            route.limiter.message ?= 'You are doing that too much.'
            route.limiter.villianyScore ?= 20

Add a validator, where we'll check the threshold.

            route.middleware[index] = (req, res, next) ->

              {
                excludedKeys
                instance
                message
                villianyScore
              } = route.limiter

Allow packages to check and optionally skip the limiter.

#### Invoke hook `shrubLimiterCheck`.

              for rule in pkgman.invokeFlat 'shrubLimiterCheck', req
                continue unless rule?
                return next() if SKIP is rule

              fingerprint = new Fingerprint req

              inlineKeys = fingerprint.inlineKeys excludedKeys

Build a nice error message for the client, so they hopefully will stop doing
that.

              sendLimiterError = ->
                instance.ttl(inlineKeys).then (ttl) ->
                  next errors.instantiate(
                    'limiterThreshold'
                    message
                    moment().add('seconds', ttl).fromNow()
                  )

Accrue a hit and check the threshold.

              instance.accrueAndCheckThreshold(inlineKeys).then((isLimited) ->
                return next() unless isLimited

#### Invoke hook `shrubVillianyReport`.

                Promise.all(
                  pkgman.invokeFlat(
                    'shrubVillianyReport'
                    req
                    villianyScore
                    "rpc://#{path}:limiter"
                    excludedKeys
                  )

                ).then (reports) ->

Only send an error if the user wasn't banned for this.

                  if reports.filter((isBanned) -> !!isBanned).length is 0
                    sendLimiterError()

              ).catch next

#### Implements hook `shrubTransmittableErrors`.

Just defer to client, where the error is defined.

      registrar.registerHook 'shrubTransmittableErrors', require('./client').shrubTransmittableErrors

    exports.Limiter = Limiter = require './limiter'

# Rate limiter

*Limits the rate at which clients can do certain operations, like call RPC
routes.*

    pkgman = require 'pkgman'

    exports.SKIP = SKIP = {}

A limiter on a route is defined like:

```javascript

registrar.registerHook('shrubRpcRoutes', function() {

  var shrubLimiter = require 'shrub-limiter'
  var Limiter = shrubLimiter.Limiter;
  var LimiterMiddleware = shrubLimiter.LimiterMiddleware;

  var routes = []

  routes.push({

.    path: 'my-package/route',

.    middleware: [

.      ...

.      'shrub-villiany' // Include if limit infractions lead to eventual ban

.      new LimiterMiddleware(
.        limiterDefinitionObject
.      )

.      ...

.    ]

  });

  return routes;
});

```

<small>***NOTE:*** *Ignore the leading dots, they are a result of literate coffee
limitations.*</small>

Where `limiterDefinitionObject` above is defined as an object with the
following properties:

* `threshold`: The [threshold](./limiter#threshold) for this limiter.
* `message`: The message returned to the client when the threshold is
  passed.
* `ignoreKeys`: The
  [fingerprint keys](source/server/fingerprint) to ignore when
  determining the total limit.
* `villianyScore`: The score accumulated when this limit is crossed.

### LimiterMiddleware

    exports.LimiterMiddleware = class LimiterMiddleware

      constructor: (@config) ->

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubOrmCollections`.

      registrar.registerHook 'shrubOrmCollections', ->

        _ = require 'lodash'

        Limit =

          autoPK: false

          associations: [
            alias: 'scores'
          ]

          attributes:

## Limit#key

*The limiter key.*

            key:
              type: 'string'
              primaryKey: true

## Limit#scores

*Scores accrued for this limit.*

            scores:
              collection: 'shrub-limit-score'
              via: 'limit'

## Limit#accrue

* (Number) `score` - The numeric score to accrue.

*Accrue a score for this limit.*

            accrue: (score) ->
              @scores.add score: score

              return this

## Limit#passed

* (Number) `threshold` - The threshold duration in seconds.

*Check whether a limit has passed the time threshold.*

            passed: (threshold) -> 0 >= @ttl threshold

## Limit#reset

*Reset scores and created time.*

            reset: ->
              @scores.remove id for id in _.pluck @scores, 'id'
              @createdAt = new Date()

              return this

## Limit#reset

*Get the sum of all scores for this limit.*

            score: ->
              _.pluck(@scores, 'score').reduce ((l, r) -> l + r), 0

## Limit#ttl

* (Number) `threshold` - The threshold duration in seconds.

*Get the current time-to-live for this limit.*

            ttl: (threshold) ->
              diff = (Date.now() - @createdAt.getTime()) / 1000
              Math.ceil threshold - diff

        LimitScore =

          attributes:

            score: 'integer'

            limit: model: 'shrub-limit'

        'shrub-limit': Limit
        'shrub-limit-score': LimitScore

#### Implements hook `shrubRpcRoutesAlter`.

Allow RPC routes definitions to specify rate limiters.

      registrar.registerHook 'shrubRpcRoutesAlter', (routes) ->

        Promise = require 'bluebird'
        moment = require 'moment'

        errors = require 'errors'

Check all routes' middleware for limiter definitions.

        Object.keys(routes).forEach (path) ->
          route = routes[path]

          Fingerprint = require 'fingerprint'

          for fn, index in route.middleware
            continue unless fn instanceof exports.LimiterMiddleware

            route.limiter = fn.config

Create a limiter based on the threshold defined.

            route.limiter.instance = new Limiter(
              "rpc://#{path}", route.limiter.threshold
            )

Set defaults.

            route.limiter.excludedKeys ?= []
            route.limiter.message ?= 'You are doing that too much.'
            route.limiter.villianyScore ?= 20

Add a validator, where we'll check the threshold.

            route.middleware[index] = (req, res, next) ->

              {
                excludedKeys
                instance
                message
                villianyScore
              } = route.limiter

Allow packages to check and optionally skip the limiter.

#### Invoke hook `shrubLimiterCheck`.

              for rule in pkgman.invokeFlat 'shrubLimiterCheck', req
                continue unless rule?
                return next() if SKIP is rule

              fingerprint = new Fingerprint req

              inlineKeys = fingerprint.inlineKeys excludedKeys

Build a nice error message for the client, so they hopefully will stop doing
that.

              sendLimiterError = ->
                instance.ttl(inlineKeys).then (ttl) ->
                  next errors.instantiate(
                    'limiterThreshold'
                    message
                    moment().add('seconds', ttl).fromNow()
                  )

Accrue a hit and check the threshold.

              instance.accrueAndCheckThreshold(inlineKeys).then((isLimited) ->
                return next() unless isLimited

#### Invoke hook `shrubVillianyReport`.

                Promise.all(
                  pkgman.invokeFlat(
                    'shrubVillianyReport'
                    req
                    villianyScore
                    "rpc://#{path}:limiter"
                    excludedKeys
                  )

                ).then (reports) ->

Only send an error if the user wasn't banned for this.

                  if reports.filter((isBanned) -> !!isBanned).length is 0
                    sendLimiterError()

              ).catch next

#### Implements hook `shrubTransmittableErrors`.

Just defer to client, where the error is defined.

      registrar.registerHook 'shrubTransmittableErrors', require('./client').shrubTransmittableErrors

    exports.Limiter = Limiter = require './limiter'


code block after list seems to be confusing the markdown parser

# The build script

This is a very simple build script that puts together the YAML + JADE page files
and the pure JADE template files. It also builds the blog index.

Load modules

    fs = require 'fs'
    mkdirp = require('mkdirp').sync;
    jade = require 'jade'
    yaml = require 'js-yaml'
    config = require './config'

### Markdown

Add custom markdown parser
with custom code parsing function
that highlights with Pygments

Further reading:

- [Marked overriding-renderer-methods](https://www.npmjs.com/package/marked#overriding-renderer-methods)
- [Node child_process.execSync](http://nodejs.org/docs/v0.12.0/api/child_process.html#child_process_child_process_execsync_command_options)
- [Jade How to define/install custom filter?](https://github.com/jadejs/jade/issues/1055)
- [Pygments lexers](http://pygments.org/docs/lexers/)

**note**: We are overriding `renderer.code`
instead of `renderer.options.highlight`
because it wraps the highlihter result in unnecessary `<pre><code>`.

**note**: Since Jade doesn't support async filters,
we have to use `child_process.execSync`.
This requires Node >= 0.11.12

    execSync = (require 'child_process').execSync
    marked = require 'marked'

    renderer = new marked.Renderer
    renderer.code = (code, lexer = 'text') ->
        result = execSync "pygmentize -l #{lexer} -f html",
            input: code
        return result.toString()

    marked.setOptions
        renderer: renderer

    jade.filters.markdown = marked

### Template loader

Templates are different from pages in that they don't have a YAML front matter.
They are written in clean jade and can extend and include other templates.

    class Template
        constructor: (@name = 'page', @location = config.templatesPath) ->
        getHtml: (options) ->
            cwd = process.cwd()
            options.pretty = config.pretty
            options.filename = @name
            try
                process.chdir @location
                content = fs.readFileSync "#{@name}.jade", 'utf8'
                @html = jade.render content, options
            catch error
                console.log error
            finally
                process.chdir cwd
            return @html

## Page loader

    class Page

A nice /regexp?/ from the
[dworthen/js-yaml-front-matter](https://github.com/dworthen/js-yaml-front-matter/blob/master/lib/js-yaml-front.js)
repo to separate the YAML front matter from the JADE page content.

        re: /^(-{3}(?:\n|\r)([\w\W]+?)(?:\n|\r)-{3})?([\w\W]*)*/

Set the file name and location

        constructor: (@pageFile, @location = config.pagesPath) ->

Render the HTML

        render: ->

Make sure we have content

            if not @content?
                if not @pageFile?
                    throw new Error 'pageFile not set'
                location = "#{@location}/#{@pageFile}"
                @content = fs.readFileSync location, 'utf8'

Parse the content

            parts = @re.exec @content
            if ! @frontMatter?
                @frontMatter = if parts[2]? then yaml.safeLoad parts[2] else {}
            this[key] = value for key, value of @frontMatter
            if ! @containerContent?
                @containerContent = jade.render parts[3] or '',
                    filename: @pageFile
                    pretty: config.pretty

Parse the template

            template = new Template @template or null
            @html = template.getHtml this

Write the page into the output directory. I might move this to a separate
function (class) later on maybe?

        write: ->
            folder = "#{config.htmlPath}#{@url}"
            mkdirp folder unless fs.existsSync folder
            fs.writeFileSync "#{folder}/index.html", @html

#### Blog

It's the blog index page.

    class Blog extends Page
        posts: []
        content: ''
        template: 'blog'
        title: 'Blog'
        url: '/blog'

#### Pages

Iterate through a given directory and process the given pages.

Each page is pushed into a list of pages that will later be used for blog building
and sitemap.xml

    class Pages
        constructor: (@location) ->
            @pages = []
        render: ->
            for pageFile in (fs.readdirSync @location).reverse()
                page = new Page pageFile, @location
                page.render()
                page.write()
                @pages.push page

#### Blogs

Do the Pages thing and build a blog index on top.

    class Blogs extends Pages
        render: ->
            super()
            blog = new Blog
            blog.posts = @pages
            do blog.render
            do blog.write

# Render

    pages = new Pages config.pagesPath
    pages.render()
    blogs = new Blogs config.blogPath
    blogs.render()

# The build script

This is a very simple build script that puts together the YAML + JADE page files
and the pure JADE template files. It also builds the blog index.

Load modules

    fs = require 'fs'
    mkdirp = require('mkdirp').sync;
    jade = require 'jade'
    yaml = require 'js-yaml'
    config = require './config'

### Markdown

Add custom markdown parser
with custom code parsing function
that highlights with Pygments

**note**: We are overriding `renderer.code`
instead of `renderer.options.highlight`
because it wraps the highlihter result in unnecessary `<pre><code>`.

**note**: Since Jade doesn't support async filters,
we have to use `child_process.execSync`.
This requires Node >= 0.11.12

Further reading:

- [Marked overriding-renderer-methods](https://www.npmjs.com/package/marked#overriding-renderer-methods)
- [Node child_process.execSync](http://nodejs.org/docs/v0.12.0/api/child_process.html#child_process_child_process_execsync_command_options)
- [Jade How to define/install custom filter?](https://github.com/jadejs/jade/issues/1055)
- [Pygments lexers](http://pygments.org/docs/lexers/)

    execSync = (require 'child_process').execSync
    marked = require 'marked'

    renderer = new marked.Renderer
    renderer.code = (code, lexer = 'text') ->
        result = execSync "pygmentize -l #{lexer} -f html",
            input: code
        return result.toString()

    marked.setOptions
        renderer: renderer

    jade.filters.markdown = marked

### Template loader

Templates are different from pages in that they don't have a YAML front matter.
They are written in clean jade and can extend and include other templates.

    class Template
        constructor: (@name = 'page', @location = config.templatesPath) ->
        getHtml: (options) ->
            cwd = process.cwd()
            options.pretty = config.pretty
            options.filename = @name
            try
                process.chdir @location
                content = fs.readFileSync "#{@name}.jade", 'utf8'
                @html = jade.render content, options
            catch error
                console.log error
            finally
                process.chdir cwd
            return @html

## Page loader

    class Page

A nice /regexp?/ from the
[dworthen/js-yaml-front-matter](https://github.com/dworthen/js-yaml-front-matter/blob/master/lib/js-yaml-front.js)
repo to separate the YAML front matter from the JADE page content.

        re: /^(-{3}(?:\n|\r)([\w\W]+?)(?:\n|\r)-{3})?([\w\W]*)*/

Set the file name and location

        constructor: (@pageFile, @location = config.pagesPath) ->

Render the HTML

        render: ->

Make sure we have content

            if not @content?
                if not @pageFile?
                    throw new Error 'pageFile not set'
                location = "#{@location}/#{@pageFile}"
                @content = fs.readFileSync location, 'utf8'

Parse the content

            parts = @re.exec @content
            if ! @frontMatter?
                @frontMatter = if parts[2]? then yaml.safeLoad parts[2] else {}
            this[key] = value for key, value of @frontMatter
            if ! @containerContent?
                @containerContent = jade.render parts[3] or '',
                    filename: @pageFile
                    pretty: config.pretty

Parse the template

            template = new Template @template or null
            @html = template.getHtml this

Write the page into the output directory. I might move this to a separate
function (class) later on maybe?

        write: ->
            folder = "#{config.htmlPath}#{@url}"
            mkdirp folder unless fs.existsSync folder
            fs.writeFileSync "#{folder}/index.html", @html

#### Blog

It's the blog index page.

    class Blog extends Page
        posts: []
        content: ''
        template: 'blog'
        title: 'Blog'
        url: '/blog'

#### Pages

Iterate through a given directory and process the given pages.

Each page is pushed into a list of pages that will later be used for blog building
and sitemap.xml

    class Pages
        constructor: (@location) ->
            @pages = []
        render: ->
            for pageFile in (fs.readdirSync @location).reverse()
                page = new Page pageFile, @location
                page.render()
                page.write()
                @pages.push page

#### Blogs

Do the Pages thing and build a blog index on top.

    class Blogs extends Pages
        render: ->
            super()
            blog = new Blog
            blog.posts = @pages
            do blog.render
            do blog.write

# Render

    pages = new Pages config.pagesPath
    pages.render()
    blogs = new Blogs config.blogPath
    blogs.render()