Make a comment a bit more descriptive.

Make a comment a bit more descriptive.

Routing
=======
This file serves as the "glue" between the express router and sanity. Basically, we want a rails-esque routing system with all the routes declared in one location.  One advantage over rails, though, is that we're going to allow some degree of function composition in that we can declare multiple, reusable actions per-route, then let them pass the return value from one to the next.

This is done via unapologetic use of Promises.

##Libraries

    Promise = require 'bluebird'
    fs = Promise.promisifyAll require 'fs'
    _ = require 'lodash'

As a note, the `Promise.promisifyAll` function simply adds `Async` to the end of the methods in `fs` and subsequently allows Promises to be used instead of callbacks.

##Local Modules

    getControllers = require './getControllers'
    policies = require './policies'
    bodyParser = require './bodyParser'

Let's kickstart this router.

    module.exports = (app) ->

-----------

This grabs the controllers and returns back a promise'd object of them. It made more sense to put this in a separate file, since it'sarguably useful in its own right.

        getControllers()

Once we've gotten all the controllers, we'll move on

        .then (controllerObject) ->

Let's load in the routes file

            configuredRoutes = require '../config/routes'

Let's loop through the routes file and do the appropriate mapping.[1]

            _.each configuredRoutes, (totalString, route) ->

Routes are stored like METHOD /route, so we'll split on spaces. To make this a bit more dev-friendly, let's get rid of redundant spaces and newlines so that we're not punishing devs for using extra whitespace.

                [method, endpoint] = route
                             .replace /(?:\r\n|\r|\n)/g, ' '
                             .replace /\s\s+/g, ' '
                             .trim()
                             .split ' '

-----------

This bigass thing here is for dev-friendliness.  I don't want to punish people for separating controller calls to multiple lines if they want, and I don't want punish them for adding multiple spaces.  Subsequently, I replace newlines with a  space, then replace extra spaces down to one space, trim it, and split on the @ sign so I can make the dichotomy between application logic and error-handling logic. Utilizing Coffee's "multi-return" thing, I can set the values pretty cleanly, but not before I make sure the values are trimmed.

                [actionString, catchString] = totalString
                                  .replace /(?:\r\n|\r|\n)/g, ' '
                                  .replace /\s\s+/g, ' '
                                  .trim()
                                  .split '@'
                                  .map (i) -> do i.trim
-----------

Again, just make it cleaner, we'll utilize the "multi-return" thing coffeescript does. Since I don't want a hard requirement for a catch to exist, I will put a conditional to see if the catch is defined.

                [catchController,catchFunction] = catchString.split '.' if catchString?

If we have a catch defined, awesome, else we'll just feed in an empty function.

                catcher = controllerObject[catchController]?[catchFunction] || ->

Split the routes on a space so as to separate individual action handlers.

                allRoutes = actionString.split ' '

-------

Loop through all the actions that are provided for that route, look them up, return back the handles on the function. So as to save a "push" command we'll use a map

                actionHandles = _.map allRoutes, (a) ->

First we need to separate out the error handling stuff from the actual program, so let's split that out, and utilize the multi-return value feature of coffeescript.

                    [actionStuff, errorStuff] = a.split '!'

Since I don't want to make a hard requirement to provide an error-handler, let's put a put quick "if" at the end of this to make sure we have errorstuff to assign.

                    [errorController, errorAction] = errorStuff.split '.' if errorStuff?

Let's parse out the controller and action.

                    [myController, myAction] = actionStuff.split '.'

Now let's grab the appropriate stuff out of the controllers.

                    finalAction =  controllerObject[myController][myAction]
                    finalError = controllerObject[errorController]?[errorAction]

Since everything is parsed out, let's just wrap this in an object so as to easily pipe into the promises.

                    finalObject =
                        action: finalAction
                        error: finalError
                        controllerName: myController
                        actionName: myAction

Once everything is done, let's just return out of the map and move on.

                    return finalObject

The `wrapper` function.
-----------------------

This here is the glue that does the joining of the actual functions.  In a nutshell, when the request it made, it should run `wrapper`, which will loop through the functions that were returned by the previous map, and run them sequentially as part of the promise chain.  I would like to eventually add a mechanism in which to do this in parallel (instead of just sequentially) eventually.

                wrapper = (req, res) ->

We need to make sure the user is allowed to use everything that this route has to offer.  Due to the beauty of Bluebird, if this this trips up, it'll just kill the promise chain and make it so that we don't go any farther than we're allowed to.

                        bodyParser req
                        .then (updatedReq) ->
                            policies actionHandles, updatedReq, res

Once we've gotten all the handles on the functions we need to call, we can concat it to all previous promises. Afterwards we want these to run sequentially, so we use the reduce function to run them, then converge into a single, final promise.

                            finalPromise =
                                _.chain [authPromise]
                                .flatten()
                                .concat actionHandles
                                .reduce (cur, next) ->
                                    cur.then next.action, next.error
                                .value()

Everything should be done.  We can finally render a template or return back JSON depending on what they did on that last function

                            finalPromise.then (endData) ->

What happens now is pretty simple.  A requirement for frameworkey is that you return an object with your data and the `renderType` property. From there it's pretty straightforward.

                                if endData.renderType.toLowerCase() == 'html'
                                    # We used "toLowerCase" to make it more dev-friendly.
                                    res.render endData.page
                                else if endData.renderType.toLowerCase() == 'json'
                                    res.send endData.data

We'll use the global catch defined at the end of the actions to handle residual errors.  If there's an issue, we go here. We can default to an empty function if there's an issue.

                            finalPromise.catch catcher

As stated above, wrapper will return a new function based on what we send in for "allRoutes".  We're adding the "toLowerCase()" to make this a bit more dev-friendly.

                app[do method.toLowerCase] endpoint, wrapper

[1]: I *really* hate how the value comes before the key in Lodash

Routing
=======
This file serves as the "glue" between the express router and sanity. Basically, we want a rails-esque routing system with all the routes declared in one location.  One advantage over rails, though, is that we're going to allow some degree of function composition in that we can declare multiple, reusable actions per-route, then let them pass the return value from one to the next.

This is done via unapologetic use of Promises.

##Libraries

    Promise = require 'bluebird'
    fs = Promise.promisifyAll require 'fs'
    _ = require 'lodash'

As a note, the `Promise.promisifyAll` function simply adds `Async` to the end of the methods in `fs` and subsequently allows Promises to be used instead of callbacks.

##Local Modules

    getControllers = require './getControllers'
    policies = require './policies'
    bodyParser = require './bodyParser'

Let's kickstart this router.

    module.exports = (app) ->

-----------

This grabs the controllers and returns back a promise'd object of them. It made more sense to put this in a separate file, since it'sarguably useful in its own right.

        getControllers()

Once we've gotten all the controllers, we'll move on

        .then (controllerObject) ->

Let's load in the routes file

            configuredRoutes = require '../config/routes'

Let's loop through the routes file and do the appropriate mapping.[1]

            _.each configuredRoutes, (totalString, route) ->

Routes are stored like METHOD /route, so we'll split on spaces. To make this a bit more dev-friendly, let's get rid of redundant spaces and newlines.

                [method, endpoint] = route
                             .replace /(?:\r\n|\r|\n)/g, ' '
                             .replace /\s\s+/g, ' '
                             .trim()
                             .split ' '

-----------

This bigass thing here is for dev-friendliness.  I don't want to punish people for separating controller calls to multiple lines if they want, and I don't want punish them for adding multiple spaces.  Subsequently, I replace newlines with a  space, then replace extra spaces down to one space, trim it, and split on the @ sign so I can make the dichotomy between application logic and error-handling logic. Utilizing Coffee's "multi-return" thing, I can set the values pretty cleanly, but not before I make sure the values are trimmed.

                [actionString, catchString] = totalString
                                  .replace /(?:\r\n|\r|\n)/g, ' '
                                  .replace /\s\s+/g, ' '
                                  .trim()
                                  .split '@'
                                  .map (i) -> do i.trim
-----------

Again, just make it cleaner, we'll utilize the "multi-return" thing coffeescript does. Since I don't want a hard requirement for a catch to exist, I will put a conditional to see if the catch is defined.

                [catchController,catchFunction] = catchString.split '.' if catchString?

If we have a catch defined, awesome, else we'll just feed in an empty function.

                catcher = controllerObject[catchController]?[catchFunction] || ->

Split the routes on a space so as to separate individual action handlers.

                allRoutes = actionString.split ' '

-------

Loop through all the actions that are provided for that route, look them up, return back the handles on the function. So as to save a "push" command we'll use a map

                actionHandles = _.map allRoutes, (a) ->

First we need to separate out the error handling stuff from the actual program, so let's split that out, and utilize the multi-return value feature of coffeescript.

                    [actionStuff, errorStuff] = a.split '!'

Since I don't want to make a hard requirement to provide an error-handler, let's put a put quick "if" at the end of this to make sure we have errorstuff to assign.

                    [errorController, errorAction] = errorStuff.split '.' if errorStuff?

Let's parse out the controller and action.

                    [myController, myAction] = actionStuff.split '.'

Now let's grab the appropriate stuff out of the controllers.

                    finalAction =  controllerObject[myController][myAction]
                    finalError = controllerObject[errorController]?[errorAction]

Since everything is parsed out, let's just wrap this in an object so as to easily pipe into the promises.

                    finalObject =
                        action: finalAction
                        error: finalError
                        controllerName: myController
                        actionName: myAction

Once everything is done, let's just return out of the map and move on.

                    return finalObject

The `wrapper` function.
-----------------------

This here is the glue that does the joining of the actual functions.  In a nutshell, when the request it made, it should run `wrapper`, which will loop through the functions that were returned by the previous map, and run them sequentially as part of the promise chain.  I would like to eventually add a mechanism in which to do this in parallel (instead of just sequentially) eventually.

                wrapper = (req, res) ->

We need to make sure the user is allowed to use everything that this route has to offer.  Due to the beauty of Bluebird, if this this trips up, it'll just kill the promise chain and make it so that we don't go any farther than we're allowed to.

                        bodyParser req
                        .then (updatedReq) ->
                            policies actionHandles, updatedReq, res

Once we've gotten all the handles on the functions we need to call, we can concat it to all previous promises. Afterwards we want these to run sequentially, so we use the reduce function to run them, then converge into a single, final promise.

                            finalPromise =
                                _.chain [authPromise]
                                .flatten()
                                .concat actionHandles
                                .reduce (cur, next) ->
                                    cur.then next.action, next.error
                                .value()

Everything should be done.  We can finally render a template or return back JSON depending on what they did on that last function

                            finalPromise.then (endData) ->

What happens now is pretty simple.  A requirement for frameworkey is that you return an object with your data and the `renderType` property. From there it's pretty straightforward.

                                if endData.renderType.toLowerCase() == 'html'
                                    # We used "toLowerCase" to make it more dev-friendly.
                                    res.render endData.page
                                else if endData.renderType.toLowerCase() == 'json'
                                    res.send endData.data

We'll use the global catch defined at the end of the actions to handle residual errors.  If there's an issue, we go here. We can default to an empty function if there's an issue.

                            finalPromise.catch catcher

As stated above, wrapper will return a new function based on what we send in for "allRoutes".  We're adding the "toLowerCase()" to make this a bit more dev-friendly.

                app[do method.toLowerCase] endpoint, wrapper

[1]: I *really* hate how the value comes before the key in Lodash


Stop performing unnecessary test when calling initialize_drawing_context

    Module = require '../../module'
    q      = require 'q'

    class PngRenderer extends Module
      deps: [ 'fs', 'canvas', 'path', 'config' ]
      pub:  [ 'render', 'flush' ]

      @draw_to: undefined
      @ctx:     undefined

      initialize: (params) =>
        deferred = q.defer()

        super()
          .then =>
            @initialize_drawing_context()

            deferred.resolve @

        deferred.promise

      initialize_drawing_context: =>
        width  = @config.width  * @config.grid[0].length
        height = @config.height * @config.grid.length

        PngRenderer.draw_to = new @canvas width, height
        PngRenderer.ctx     = PngRenderer.draw_to.getContext '2d'

      render: (path) => @done @do_render path

      flush: (level) =>
        stream = @fs.createWriteStream @path.join __dirname, '..', '..', '..', 'output', "#{level}.png"

        for row, r in @config.grid
          for cell, c in @config.grid[r]
            @config.grid[r][c] = false

        stream.on 'finish', => @done 'Persisted', location: level

        PngRenderer.draw_to.createPNGStream().pipe stream

    module.exports = PngRenderer

    Module = require '../../module'
    q      = require 'q'

    class PngRenderer extends Module
      deps: [ 'fs', 'canvas', 'path', 'config' ]
      pub:  [ 'render', 'flush' ]

      @draw_to: undefined
      @ctx:     undefined

      initialize: (params) =>
        deferred = q.defer()

        super()
          .then =>
            @initialize_drawing_context() unless PngRenderer.draw_to?

            deferred.resolve @

        deferred.promise

      initialize_drawing_context: =>
        width  = @config.width  * @config.grid[0].length
        height = @config.height * @config.grid.length

        PngRenderer.draw_to = new @canvas width, height
        PngRenderer.ctx     = PngRenderer.draw_to.getContext '2d'

      render: (path) => @done @do_render path

      flush: (level) =>
        stream = @fs.createWriteStream @path.join __dirname, '..', '..', '..', 'output', "#{level}.png"

        for row, r in @config.grid
          for cell, c in @config.grid[r]
            @config.grid[r][c] = false

        stream.on 'finish', => @done 'Persisted', location: level

        PngRenderer.draw_to.createPNGStream().pipe stream

    module.exports = PngRenderer


Refactored statuses into a var to elminate a bit of duplication

    Madul = require 'madul'

    STATUSES =
      COMPLETE: 'COMPLETE'
      ERROR:    'ERROR'
      PROGRESS: 'PROGRESS'

    EXCLUDE = [
      'MODULE'
      'ACTION'
      'EXECUTE'
    ]

    class Server extends Madul

      deps: [ 'ws' ]

      boot: (args, done) ->
        wss = new @ws.Server port: args.ws.port

        wss.on 'connection', (ws) =>
          ws.on 'message', (mess) =>
            try
              input = JSON.parse mess
            catch e
              return @_notify ws, STATUSES.ERROR, "Could not parse as JSON: #{mess}"

            @handle input
              .then (output) => @_notify ws, STATUSES.COMPLETE, output
              .catch   (err) => @_notify ws, STATUSES.ERROR,    err.args? || err
              .progress (up) => @_notify ws, STATUSES.PROGRESS, up

        done()

      _notify: (socket, status, data) =>
        if status == STATUSES.ERROR
          out = { status, message: data }
        else
          out = { status, data }

        socket.send JSON.stringify out

      handle:
        validate:
          KEY:    [ '.is_present', '.hasnt_expired' ]
          MODULE: '.is_present'
          ACTION: '.is_present'
        before:   '.init_execution_context'
        behavior: (input) ->
          args = { }

          for own key, val of input
            if key != 'MODULE' && key != 'ACTION' && key != 'EXECUTE'
              args[key] = val

          input.EXECUTE args
            .then     (output) => input.done   output
            .catch    (err)    => input.fail   err
            .progress (delta)  => input.update delta

    module.exports = Server

    Madul = require 'madul'

    class Server extends Madul

      deps: [ 'ws' ]

      boot: (args, done) ->
        wss = new @ws.Server port: args.ws.port

        wss.on 'connection', (ws) =>
          ws.on 'message', (mess) =>
            try
              input = JSON.parse mess
            catch e
              return @_notify ws, 'ERROR', "Could not parse as JSON: #{mess}"

            @handle input
              .then (output) => @_notify ws, 'COMPLETE', output
              .catch   (err) => @_notify ws, 'ERROR',    err.message? || err
              .progress (up) => @_notify ws, 'PROGRESS', up

        done()

      _notify: (socket, status, data) =>
        if status == 'ERROR'
          out = { status, message: data }
        else
          out = { status, data }

        socket.send JSON.stringify out

      handle:
        validate:
          KEY:    [ '.is_present', '.hasnt_expired' ]
          MODULE: '.is_present'
          ACTION: '.is_present'
        before:   '.init_execution_context'
        behavior: (input) ->
          args = { }

          for own key, val of input
            if key != 'MODULE' && key != 'ACTION' && key != 'EXECUTE'
              args[key] = val

          input.EXECUTE args
            .then     (output) => input.done   output
            .catch    (err)    => input.fail   err
            .progress (delta)  => input.update delta

    module.exports = Server


Refactored dep loading logic to use new helper method


Fix build path

Fix build path

# Node.js Bindings for Link Grammar

The parser is built using the awesome ffi library which allows
us to communicate with a native library under the covers.
Along with ffi, we also use ref library to reference the native
objects used by the library.

    ffi = require 'ffi'
    ref = require 'ref'
    Struct = require 'ref-struct'
    _ = require 'underscore'

Easier references to base types of data.

    pointerType = 'pointer'
    string = ref.types.CString
    int = ref.types.int

These are just references to different native structs, which are
all just pointers because we never use their actual referenced object.

    ParseOptions = pointerType
    Dictionary = pointerType
    Sentence = pointerType
    Linkage = pointerType

Here are the templates for the native functions we will use.

    apiTemplate =
        parse_options_create: [ ParseOptions, [ ] ]
        parse_options_set_null_block: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_islands_ok: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_verbosity: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_allow_null: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_max_null_count: [ ref.types.void, [ ParseOptions, int ] ]
        dictionary_create: [ Dictionary, [ string, string, string, string ] ]
        sentence_create: [ Sentence, [ string, Dictionary ] ]
        sentence_parse: [ int, [ Sentence, ParseOptions ] ]
        sentence_length: [ int, [ Sentence ] ]
        sentence_get_word: [ string, [ Sentence, int ] ]
        linkage_create: [ Linkage, [ int, Sentence, ParseOptions ] ]
        linkage_print_diagram: [ string, [ Linkage ] ]
        linkage_get_num_links: [ int, [ Linkage ] ]
        linkage_get_link_label: [ string, [ Linkage, int ] ]
        linkage_get_link_llabel: [ string, [ Linkage, int ] ]
        linkage_get_link_rlabel: [ string, [ Linkage, int ] ]
        linkage_get_word: [ string, [ Linkage, int ] ]
        linkage_get_link_lword: [ int, [ Linkage, int ] ]
        linkage_get_link_rword: [ int, [ Linkage, int ] ]

Load the library.

    libPath = __dirname + '/../../../build/link-grammar/.libs/liblink-grammar.so'
    lib = ffi.Library libPath, apiTemplate
    defaultDataPath = __dirname + '/../../../data/en/'

Default configuration for data paths.

    defaultConfig =
        lang: 'en'
        verbose: false

Main parser class which interfaces the native library to make
it very simple to get Link Grammar data from an input string.

    class LinkGrammar

A few utility methods for the parser.

        constructor: (config) ->
            @config = _.extend config or {}, defaultConfig
            @options = lib.parse_options_create()
            lib.parse_options_set_verbosity @options, (if @config.verbose then 1  else 0)
            lib.parse_options_set_allow_null @options, 1
            lib.parse_options_set_max_null_count @options, 3
            @dictionary = lib.dictionary_create @config.lang

Parse input, and return linkage, if it exists.

        parse: (input, index) ->
            sentence = lib.sentence_create input, @dictionary
            numLinkages = lib.sentence_parse sentence, @options
            if numLinkages > 0
              new Linkage lib.linkage_create index or 0, sentence, @options
            else
              throw new Error('No linkages found')

Linkage class which allows for more specific parsing of grammar.

    class Linkage

        constructor: (@linkage) ->
            @links = @getLinks()
            @words = @getWords()

Get array of grammar links based on linkage.

        getLinks: ->
            _(lib.linkage_get_num_links @linkage).times ((index) ->
                leftIndex = lib.linkage_get_link_lword @linkage, index
                rightIndex = lib.linkage_get_link_rword @linkage, index
                link =
                    label: lib.linkage_get_link_label @linkage, index
                    left:
                        label: lib.linkage_get_link_llabel @linkage, index
                        word: lib.linkage_get_word @linkage, leftIndex
                        index: leftIndex
                    right:
                        label: lib.linkage_get_link_rlabel @linkage, index
                        word: lib.linkage_get_word @linkage, rightIndex
                        index: rightIndex
                if link.left.word.indexOf '.' isnt -1
                    temp = link.left.word.split '.'
                    link.left.word = temp[0]
                    link.left.type = temp[1]
                if link.right.word.indexOf '.' isnt -1
                    temp = link.right.word.split '.'
                    link.right.word = temp[0]
                    link.right.type = temp[1]
                link
            ), @

Get parsed words with their grammar type and index

        getWords: ->
            _.chain(@links)
                .map (link) -> [link.left, link.right]
                .flatten()
                .uniq (link) -> link.word
                .value()

Get list of links by specific label type

        linksByLabel: (labelPattern) ->
            labelPattern = new RegExp labelPattern if typeof labelPattern is 'string'
            @links.filter (link) ->
                labelPattern.test link.left.label or labelPattern.test link.right.label

Get list of connector links for a specific word

        getConnectorWords: (common) ->
            words = []
            @links.forEach (link) ->
                if link.left.word is common
                    words.push
                        source: link.left
                        target: link.right
                if link.right.word is common
                    words.push
                        source: link.right
                        target: link.left
            words

    module.exports = LinkGrammar

# Node.js Bindings for Link Grammar

The parser is built using the awesome ffi library which allows
us to communicate with a native library under the covers.
Along with ffi, we also use ref library to reference the native
objects used by the library.

    ffi = require 'ffi'
    ref = require 'ref'
    Struct = require 'ref-struct'
    _ = require 'underscore'

Easier references to base types of data.

    pointerType = 'pointer'
    string = ref.types.CString
    int = ref.types.int

These are just references to different native structs, which are
all just pointers because we never use their actual referenced object.

    ParseOptions = pointerType
    Dictionary = pointerType
    Sentence = pointerType
    Linkage = pointerType

Here are the templates for the native functions we will use.

    apiTemplate =
        parse_options_create: [ ParseOptions, [ ] ]
        parse_options_set_null_block: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_islands_ok: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_verbosity: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_allow_null: [ ref.types.void, [ ParseOptions, int ] ]
        parse_options_set_max_null_count: [ ref.types.void, [ ParseOptions, int ] ]
        dictionary_create: [ Dictionary, [ string, string, string, string ] ]
        sentence_create: [ Sentence, [ string, Dictionary ] ]
        sentence_parse: [ int, [ Sentence, ParseOptions ] ]
        sentence_length: [ int, [ Sentence ] ]
        sentence_get_word: [ string, [ Sentence, int ] ]
        linkage_create: [ Linkage, [ int, Sentence, ParseOptions ] ]
        linkage_print_diagram: [ string, [ Linkage ] ]
        linkage_get_num_links: [ int, [ Linkage ] ]
        linkage_get_link_label: [ string, [ Linkage, int ] ]
        linkage_get_link_llabel: [ string, [ Linkage, int ] ]
        linkage_get_link_rlabel: [ string, [ Linkage, int ] ]
        linkage_get_word: [ string, [ Linkage, int ] ]
        linkage_get_link_lword: [ int, [ Linkage, int ] ]
        linkage_get_link_rword: [ int, [ Linkage, int ] ]

Load the library.

    libPath = __dirname + '/../build/libparser'
    lib = ffi.Library libPath, apiTemplate
    defaultDataPath = __dirname + '/../../data/en/'

Default configuration for data paths.

    defaultConfig =
        lang: 'en'
        verbose: false

Main parser class which interfaces the native library to make
it very simple to get Link Grammar data from an input string.

    class LinkGrammar

A few utility methods for the parser.

        constructor: (config) ->
            @config = _.extend config or {}, defaultConfig
            @options = lib.parse_options_create()
            lib.parse_options_set_verbosity @options, (if @config.verbose then 1  else 0)
            lib.parse_options_set_allow_null @options, 1
            lib.parse_options_set_max_null_count @options, 3
            @dictionary = lib.dictionary_create @config.lang

Parse input, and return linkage, if it exists.

        parse: (input, index) ->
            sentence = lib.sentence_create input, @dictionary
            numLinkages = lib.sentence_parse sentence, @options
            if numLinkages > 0
              new Linkage lib.linkage_create index or 0, sentence, @options
            else
              throw new Error('No linkages found')

Linkage class which allows for more specific parsing of grammar.

    class Linkage

        constructor: (@linkage) ->
            @links = @getLinks()
            @words = @getWords()

Get array of grammar links based on linkage.

        getLinks: ->
            _(lib.linkage_get_num_links @linkage).times ((index) ->
                leftIndex = lib.linkage_get_link_lword @linkage, index
                rightIndex = lib.linkage_get_link_rword @linkage, index
                link =
                    label: lib.linkage_get_link_label @linkage, index
                    left:
                        label: lib.linkage_get_link_llabel @linkage, index
                        word: lib.linkage_get_word @linkage, leftIndex
                        index: leftIndex
                    right:
                        label: lib.linkage_get_link_rlabel @linkage, index
                        word: lib.linkage_get_word @linkage, rightIndex
                        index: rightIndex
                if link.left.word.indexOf '.' isnt -1
                    temp = link.left.word.split '.'
                    link.left.word = temp[0]
                    link.left.type = temp[1]
                if link.right.word.indexOf '.' isnt -1
                    temp = link.right.word.split '.'
                    link.right.word = temp[0]
                    link.right.type = temp[1]
                link
            ), @

Get parsed words with their grammar type and index

        getWords: ->
            _.chain(@links)
                .map (link) -> [link.left, link.right]
                .flatten()
                .uniq (link) -> link.word
                .value()

Get list of links by specific label type

        linksByLabel: (labelPattern) ->
            labelPattern = new RegExp labelPattern if typeof labelPattern is 'string'
            @links.filter (link) ->
                labelPattern.test link.left.label or labelPattern.test link.right.label

Get list of connector links for a specific word

        getConnectorWords: (common) ->
            words = []
            @links.forEach (link) ->
                if link.left.word is common
                    words.push
                        source: link.left
                        target: link.right
                if link.right.word is common
                    words.push
                        source: link.right
                        target: link.left
            words

    module.exports = LinkGrammar


Removed unneeded Config instance

Removed unneeded Config instance

    `#! /usr/bin/env node
    `

    Skyll = require './skyll'
    next  = 0

    new Skyll()
      .initialize()
      .then (mod) ->
        levels = mod.config.levels

        render = (level) ->
          mod.craft level
            .then ->
              console.log 'finished rendering level', next
              render levels[next] if ++next < levels.length

        render levels[next]

    `#! /usr/bin/env node
    `

    Config = require './config'

    new Config()
      .initialize()
      .then (config) ->
        Skyll = require './skyll'
        next  = 0

        new Skyll()
          .initialize starting_row: Math.floor config.grid.length / 2
          .then (mod) ->
            render = (level) ->
              mod.craft level
                .then ->
                  console.log 'finished rendering level', next
                  render config.levels[next] if ++next < config.levels.length

            render config.levels[next]


Logging.

Logging.

This job collects data from Sonar for the Sonar keys in the `SubjectSourceIds`
collection.

    class @SonarJob extends Job
      @setupCron: (parser) ->
        parser.recur().every(1).minute()

      handleJob: ->
        for source in Sources.find({type: 'sonar'}).fetch()
          @update_project_keys source
        for subject_source_id in SubjectSourceIds.find().fetch()
          source = Sources.findOne({_id: subject_source_id.source})
          if source.type != 'sonar'
            continue
          @measure_ncloc subject_source_id, source
          @measure_duplication subject_source_id, source

      update_project_keys: (source) ->
        result = @get_project_keys_json source.url
        if result.json
          project_keys = ({_id: project.key, title: project.key} for project in result.json)
          Sources.update source._id, {$set: {ids: project_keys}}
        else
          console.log result.error_message

      get_project_keys_json: (sonar_url) ->
        try
          result = HTTP.get sonar_url + 'api/resources?format=json'
          return {json: result.data, error_message: ''}
        catch e
          return {json: null, error_message: e.message}

      measure_ncloc: (subject_source_id, source) ->
        metric = Metrics.findOne {title: "NCLOC"}
        subject = Subjects.findOne {_id: subject_source_id.subject}
        subject_metric = SubjectMetrics.findOne {subject: subject._id, metric: metric._id}
        target = subject_metric.target or metric.target
        sonar_key = subject_source_id.id
        result = @get_json source.url, sonar_key
        if result.json
          for sonar_metric in result.json[0]['msr']
            if sonar_metric['key'] == 'ncloc'
              value = sonar_metric['val']
              target_met = ncloc_meets_target(value, target)
          error_message = null
        else
          value = null
          target_met = null
          error_message = result.error_message
        insertOrUpdateMeasurement
          projectId: source.projectId
          subject_metric_id: subject_metric._id
          metric_title: metric.title
          subject_title: subject.title
          value: value
          unit: metric.unit
          target: target
          target_met: target_met
          error_message: result.error_message

      measure_duplication: (subject_source_id, source) ->
        metric = Metrics.findOne {title: "Duplication"}
        subject = Subjects.findOne {_id: subject_source_id.subject}
        subject_metric = SubjectMetrics.findOne {subject: subject._id, metric: metric._id}
        target = subject_metric.target or metric.target
        sonar_key = subject_source_id.id
        result = @get_json source.url, sonar_key
        if result.json
          for sonar_metric in result.json[0]['msr']
            if sonar_metric['key'] == 'duplicated_lines_density'
              value = sonar_metric['val']
              target_met = duplication_meets_target(value, target)
          error_message = null
        else
          value = null
          target_met = null
          error_message = result.error_message
        insertOrUpdateMeasurement
          projectId: source.projectId
          subject_metric_id: subject_metric._id
          metric_title: metric.title
          subject_title: subject.title
          value: value
          unit: metric.unit
          target: target
          target_met: target_met
          error_message: result.error_message

      get_json: (sonar_url, sonar_key) ->
        try
          result = HTTP.get sonar_url + 'api/resources?resource=' + sonar_key + '&metrics=true'
          return {json: result.data, error_message: ''}
        catch e
          return {json: null, error_message: e.message}

    Job.push new SonarJob

This job collects data from Sonar for the Sonar keys in the `SubjectSourceIds`
collection.

    class @SonarJob extends Job
      @setupCron: (parser) ->
        parser.recur().every(1).minute()

      handleJob: ->
        for source in Sources.find({type: 'sonar'}).fetch()
          @update_project_keys source
        for subject_source_id in SubjectSourceIds.find().fetch()
          source = Sources.findOne({_id: subject_source_id.source})
          if source.type != 'sonar'
            continue
          @measure_ncloc subject_source_id, source
          @measure_duplication subject_source_id, source

      update_project_keys: (source) ->
        result = @get_project_keys_json source.url
        if result.json
          project_keys = ({_id: project.key, title: project.key} for project in result.json)
          Sources.update source._id, {$set: {ids: project_keys}}

      get_project_keys_json: (sonar_url) ->
        try
          result = HTTP.get sonar_url + 'api/resources?format=json'
          return {json: result.data, error_message: ''}
        catch e
          return {json: null, error_message: e.message}

      measure_ncloc: (subject_source_id, source) ->
        metric = Metrics.findOne {title: "NCLOC"}
        subject = Subjects.findOne {_id: subject_source_id.subject}
        subject_metric = SubjectMetrics.findOne {subject: subject._id, metric: metric._id}
        target = subject_metric.target or metric.target
        sonar_key = subject_source_id.id
        result = @get_json source.url, sonar_key
        if result.json
          for sonar_metric in result.json[0]['msr']
            if sonar_metric['key'] == 'ncloc'
              value = sonar_metric['val']
              target_met = ncloc_meets_target(value, target)
          error_message = null
        else
          value = null
          target_met = null
          error_message = result.error_message
        insertOrUpdateMeasurement
          projectId: source.projectId
          subject_metric_id: subject_metric._id
          metric_title: metric.title
          subject_title: subject.title
          value: value
          unit: metric.unit
          target: target
          target_met: target_met
          error_message: result.error_message

      measure_duplication: (subject_source_id, source) ->
        metric = Metrics.findOne {title: "Duplication"}
        subject = Subjects.findOne {_id: subject_source_id.subject}
        subject_metric = SubjectMetrics.findOne {subject: subject._id, metric: metric._id}
        target = subject_metric.target or metric.target
        sonar_key = subject_source_id.id
        result = @get_json source.url, sonar_key
        if result.json
          for sonar_metric in result.json[0]['msr']
            if sonar_metric['key'] == 'duplicated_lines_density'
              value = sonar_metric['val']
              target_met = duplication_meets_target(value, target)
          error_message = null
        else
          value = null
          target_met = null
          error_message = result.error_message
        insertOrUpdateMeasurement
          projectId: source.projectId
          subject_metric_id: subject_metric._id
          metric_title: metric.title
          subject_title: subject.title
          value: value
          unit: metric.unit
          target: target
          target_met: target_met
          error_message: result.error_message

      get_json: (sonar_url, sonar_key) ->
        try
          result = HTTP.get sonar_url + 'api/resources?resource=' + sonar_key + '&metrics=true'
          return {json: result.data, error_message: ''}
        catch e
          return {json: null, error_message: e.message}

    Job.push new SonarJob


fix navbar collapse

fix navbar collapse

# Header helpers

    Template.header.events
      'click #at-nav-link': (event) ->
        if Meteor.user() then AccountsTemplates.logout()
      'click .logout': (event) ->
        AccountsTemplates.logout()
      'click a': (event) ->
        $('.navbar-collapse').collapse 'hide'

# Header helpers

    Template.header.events
      'click #at-nav-link': (event) ->
        if Meteor.user() then AccountsTemplates.logout()
      'click .logout': (event) ->
        AccountsTemplates.logout()
      'click a': (event) ->
        $('.navbar-toggle').click()


Add create snapshot

Add create snapshot

Dependencies
============

    _      = require "underscore"
    fs     = require "fs"
    path   = require "path"
    colors = require "cli-color"

VOSCO
=====

    script =

Setup
-----

      'install': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        if isInstalled then process.exit 1
        await @vosco.install defer(error)

      'uninstall': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.uninstall defer(error)

Repository
----------

      'get-status': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.getStatus defer(error, status)
        getType = (file) -> file.type
        getPath = (file) -> colors.xterm(240)("  #{file.path}")
        groups  = _.groupBy status, getType
        for group, paths of groups
          console.log """
          #{group}
          #{paths.map(getPath).join("\n")}
          """

      'get-history': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.getHistory defer(error, history)
        for commit in history
          hash = commit.hash.substr(0, 7)
          date = new Date(commit.date).toDateString()
          msg  = commit.message
          console.log colors.xterm(240)("  #{hash}  #{date}  #{msg}")

      'get-content-history': (path) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        # show warning if file doesn"t exist
        console.log "content history"

Snapshots
---------

      'preview-snapshot': (hash) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        hash = hash or 'HEAD'
        await @vosco.previewSnapshot hash, defer(error, diff)
        console.log diff

      'create-snapshot': (message) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        message = message or 'Untitled Snapshot'
        await @vosco.createSnapshot message, defer(error)

      'rollback-to-snapshot': (hash) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "rollback to snapshot"

Branches
--------

      'list-branches': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "branches list"

      'select-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "select branch"

      'create-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "create new branch"

      'delete-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "delete branch"

Export Module
-------------

    module.exports = (vosco) ->
      script.vosco = vosco
      return script

Dependencies
============

    _      = require "underscore"
    fs     = require "fs"
    path   = require "path"
    colors = require "cli-color"

VOSCO
=====

    script =

Setup
-----

      'install': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        if isInstalled then process.exit 1
        await @vosco.install defer(error)

      'uninstall': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.uninstall defer(error)

Repository
----------

      'get-status': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.getStatus defer(error, status)
        getType = (file) -> file.type
        getPath = (file) -> colors.xterm(240)("  #{file.path}")
        groups  = _.groupBy status, getType
        for group, paths of groups
          console.log """
          #{group}
          #{paths.map(getPath).join("\n")}
          """

      'get-history': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        await @vosco.getHistory defer(error, history)
        for commit in history
          hash = commit.hash.substr(0, 7)
          date = new Date(commit.date).toDateString()
          msg  = commit.message
          console.log colors.xterm(240)("  #{hash}  #{date}  #{msg}")

      'get-content-history': (path) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        # show warning if file doesn"t exist
        console.log "content history"

Snapshots
---------

      'preview-snapshot': (hash) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        hash = hash or 'HEAD'
        await @vosco.previewSnapshot hash, defer(error, diff)
        console.log diff

      'create-snapshot': (message) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "creating snapshot"

      'rollback-to-snapshot': (hash) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "rollback to snapshot"

Branches
--------

      'list-branches': () ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "branches list"

      'select-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "select branch"

      'create-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "create new branch"

      'delete-branch': (branch) ->
        await @vosco.isInstalled defer(error, isInstalled)
        unless isInstalled then process.exit 1
        console.log "delete branch"

Export Module
-------------

    module.exports = (vosco) ->
      script.vosco = vosco
      return script


Fixed bug with used utils.isServer in testing

# Testing

    'use strict'

    {utils, log, assert} = Neft
    stack = require './stack'
    logger = require './logger'
    screenshot = require './screenshot/client'

    {isArray} = Array
    {push} = Array::
    {Scope, Test, Listener} = require './structure'

    scopes = [new Scope]
    currentScope = scopes[0]

    ONLY_OPT = 1 << 1

    raportOnlyUsed = ->
        if process.env.CI
            throw new Error "Cannot use describe.only and it.only on CI"
        else
            log.warn "describe.only or it.only is used"

# describe(*String* message, *Function* tests)

    exports.describe = (msg, func, opts = 0) ->
        beforeEach = utils.NOP

        # new scope
        scope = new Scope
        scope.message = msg
        if scope.isOnly = (opts & ONLY_OPT) > 0
            stack.onlyScopes += 1
        scopes.push scope

        # before/after functions
        push.apply scope.beforeFunctions, currentScope.beforeFunctions
        push.apply scope.afterFunctions, currentScope.afterFunctions

        # save scope to parent
        currentScope.children.push scope
        scope.parent = currentScope

        # save as last
        currentScope = scope

        # children tests
        func()

        # set parent as last
        scopes.pop()
        currentScope = utils.last scopes
        return

# describe.only(*String* message, *Function* tests)

    exports.describe.only = (msg, func) ->
        raportOnlyUsed()
        exports.describe msg, func, ONLY_OPT

# it(*String* message, *Function* test)

The given test function can contains optional *callback* argument.

    exports.it = (msg, func, opts = 0) ->
        testScope = currentScope

        # new test
        test = new Test
        test.message = msg
        test.testFunction = func
        if test.isOnly = (opts & ONLY_OPT) > 0
            stack.onlyTests += 1

        # add test into scope
        scope = utils.last scopes
        scope.children.push test
        test.parent = scope

        return

# it.only(*String* message, *Function* test)

    exports.it.only = (msg, func) ->
        raportOnlyUsed()
        exports.it msg, func, ONLY_OPT

# beforeEach(*Function* code)

    exports.beforeEach = (func) ->
        currentScope.beforeFunctions.push func
        return

# afterEach(*Function* code)

    exports.afterEach = (func) ->
        currentScope.afterFunctions.push func
        return

# whenChange(*Object* watchObject, *Function* callback, [*Integer* maxDelay = `1000`])

    exports.whenChange = do ->
        listeners = []

        checkListeners = ->
            i = 0
            while i < listeners.length
                listener = listeners[i]

                if listener.test()
                    listeners.splice i, 1
                else
                    i++

            if listeners.length > 0
                setImmediate checkListeners
            return

        (obj, callback, maxDelay = 1000) ->
            listener = new Listener
            listener.object = obj
            listener.objectCopy = utils.clone(obj)
            listener.callback = callback
            listener.maxDelay = maxDelay

            if listeners.length is 0
                setImmediate checkListeners

            listeners.push listener
            return

# takeScreenshot(*String|Object* options, [*Function* callback])

    screenshotInitialized = false
    exports.takeScreenshot = (opts, callback) ->
        if typeof opts is 'string'
            opts = expected: opts

        unless opts?.expected
            throw new Error "'expected' path not set in takeScreenshot"

        {currentTest} = Test
        assert.notOk currentTest.callbackCalled, """
            takeScreenshot called but current test '#{currentTest.getFullMessage()}' \
            is not pending
        """

        currentTest.preventEnding = true

        endCurrentTest = (err) ->
            callback? err
            currentTest.preventEnding = false
            currentTest.onEnd err

        unless screenshotInitialized
            screenshotInitialized = true
            screenshot.initialize (err) ->
                if err
                    endCurrentTest err
                else
                    exports.takeScreenshot opts, callback
            return

        screenshot.take opts, endCurrentTest
        return

    runTests = ->
        [mainScope] = scopes
        logger.onTestsStart()
        mainScope.run ->
            logger.onTestsEnd()
            onTestsEnd
                status: if stack.errors.length is 0 then 'success' else 'error'
                testsAmount: stack.testsAmount
                errors: stack.errors

    onTestsEnd = (result) ->
        code = if result.status is 'success' then 0 else 1
        if process.env.NEFT_NODE
            # give logs some time to be printed int stdout
            setTimeout ->
                process.exit code
            , 100

    runAutomatically = do ->
        val = process?.env.RUN_TESTS
        if typeof val is 'string'
            val = try JSON.parse val
        val ?= true
        val

    setImmediate ->
        if runAutomatically
            runTests()

# Testing

    'use strict'

    {utils, log, assert} = Neft
    stack = require './stack'
    logger = require './logger'
    screenshot = require './screenshot/client'

    {isArray} = Array
    {push} = Array::
    {Scope, Test, Listener} = require './structure'

    scopes = [new Scope]
    currentScope = scopes[0]

    ONLY_OPT = 1 << 1

    raportOnlyUsed = ->
        if process.env.CI
            throw new Error "Cannot use describe.only and it.only on CI"
        else
            log.warn "describe.only or it.only is used"

# describe(*String* message, *Function* tests)

    exports.describe = (msg, func, opts = 0) ->
        beforeEach = utils.NOP

        # new scope
        scope = new Scope
        scope.message = msg
        if scope.isOnly = (opts & ONLY_OPT) > 0
            stack.onlyScopes += 1
        scopes.push scope

        # before/after functions
        push.apply scope.beforeFunctions, currentScope.beforeFunctions
        push.apply scope.afterFunctions, currentScope.afterFunctions

        # save scope to parent
        currentScope.children.push scope
        scope.parent = currentScope

        # save as last
        currentScope = scope

        # children tests
        func()

        # set parent as last
        scopes.pop()
        currentScope = utils.last scopes
        return

# describe.only(*String* message, *Function* tests)

    exports.describe.only = (msg, func) ->
        raportOnlyUsed()
        exports.describe msg, func, ONLY_OPT

# it(*String* message, *Function* test)

The given test function can contains optional *callback* argument.

    exports.it = (msg, func, opts = 0) ->
        testScope = currentScope

        # new test
        test = new Test
        test.message = msg
        test.testFunction = func
        if test.isOnly = (opts & ONLY_OPT) > 0
            stack.onlyTests += 1

        # add test into scope
        scope = utils.last scopes
        scope.children.push test
        test.parent = scope

        return

# it.only(*String* message, *Function* test)

    exports.it.only = (msg, func) ->
        raportOnlyUsed()
        exports.it msg, func, ONLY_OPT

# beforeEach(*Function* code)

    exports.beforeEach = (func) ->
        currentScope.beforeFunctions.push func
        return

# afterEach(*Function* code)

    exports.afterEach = (func) ->
        currentScope.afterFunctions.push func
        return

# whenChange(*Object* watchObject, *Function* callback, [*Integer* maxDelay = `1000`])

    exports.whenChange = do ->
        listeners = []

        checkListeners = ->
            i = 0
            while i < listeners.length
                listener = listeners[i]

                if listener.test()
                    listeners.splice i, 1
                else
                    i++

            if listeners.length > 0
                setImmediate checkListeners
            return

        (obj, callback, maxDelay = 1000) ->
            listener = new Listener
            listener.object = obj
            listener.objectCopy = utils.clone(obj)
            listener.callback = callback
            listener.maxDelay = maxDelay

            if listeners.length is 0
                setImmediate checkListeners

            listeners.push listener
            return

# takeScreenshot(*String|Object* options, [*Function* callback])

    screenshotInitialized = false
    exports.takeScreenshot = (opts, callback) ->
        if typeof opts is 'string'
            opts = expected: opts

        unless opts?.expected
            throw new Error "'expected' path not set in takeScreenshot"

        {currentTest} = Test
        assert.notOk currentTest.callbackCalled, """
            takeScreenshot called but current test '#{currentTest.getFullMessage()}' \
            is not pending
        """

        currentTest.preventEnding = true

        endCurrentTest = (err) ->
            callback? err
            currentTest.preventEnding = false
            currentTest.onEnd err

        unless screenshotInitialized
            screenshotInitialized = true
            screenshot.initialize (err) ->
                if err
                    endCurrentTest err
                else
                    exports.takeScreenshot opts, callback
            return

        screenshot.take opts, endCurrentTest
        return

    runTests = ->
        [mainScope] = scopes
        logger.onTestsStart()
        mainScope.run ->
            logger.onTestsEnd()
            onTestsEnd
                status: if stack.errors.length is 0 then 'success' else 'error'
                testsAmount: stack.testsAmount
                errors: stack.errors

    onTestsEnd = (result) ->
        code = if result.status is 'success' then 0 else 1
        if utils.isServer
            # give logs some time to be printed int stdout
            setTimeout ->
                process.exit code
            , 100

    runAutomatically = do ->
        val = process?.env.RUN_TESTS
        if typeof val is 'string'
            val = try JSON.parse val
        val ?= true
        val

    setImmediate ->
        if runAutomatically
            runTests()