text:
==============================================
Specializing static and media based on tenants
==============================================

Multitenant aware static and media files
----------------------------------------

If you need to have ``different static files for each tenant`` or ``upload media files to separate directories for each tenant``, you will need use the resourses bellow, otherwise the configurations bellow are not necessary.

The classical Django ``FileSystemStorage`` and ``StaticFilesStorage`` cannot make the search path for files vary based on the current tenant so it's needed to use a special one which adapt the search path based on the tenant. For using it change your ``DEFAULT_FILE_STORAGE`` setting and also ``STATICFILES_STORAGE`` setting.

Static files finders aware tenant
---------------------------------

The classical Django ``FileSystemFinder`` cannot finder path for files vary based on the current tenant so it's needed to use a special one which find ours files based on the tenant.

To do this, first we need to structure our project so that each tenant stay separated into directories and thus we have a starting point to manipulate `templates files <templates.html>`_ and ``static files`` to each tenant:

.. code-block:: python

    STATICFILES_FINDERS = [
        'django_tenants.staticfiles.finders.TenantFileSystemFinder',  # first
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
        'compressor.finders.CompressorFinder',
    ]

    # or this way

    STATICFILES_FINDERS.insert(0, "django_tenants.staticfiles.finders.TenantFileSystemFinder")

Let's imagine the following design structure:

.. code-block:: python

    your_project_dir
        ...
        tenants
            tenant_name_1  # -> same name schema_name_1
                templates
                static
            tenant_name_2  # -> same name schema_name_2
                templates
                static
        ...
        ...

To work with that structure we need tell where are the static files of each tenant, to do this, set the variable ``MULTITENANT_STATICFILES_DIRS`` in yours settings.py as bellow:

.. code-block:: python

    # in settings.py

    MULTITENANT_STATICFILES_DIRS = [
        os.path.join( "absolute/path/your/project", 'tenants/%s/static' ),
    ]

.. tip::

    To work locally in your development environment unfortunately it is necessary to set the variable ``CURRENT_SCHEMA_TO_SERVER_STATICFILES`` to the name of the current schema you are working on, because after much searching it is not possible to automatically set the current schema value because when Django is serving static files ``it does not pass through the TenantMiddleware middleware`` that is responsible for lets the current tenant available through ``from django.db import connection; connection.schema_name``. Also I tried to use ``request.path`` but ``request is also not available within FileSystemFinder``, so we have to do as below. This is necessary only to server static files locally.

    IMPORTANT: For all the other things like collectstatic files, medias files, the variable ``CURRENT_SCHEMA_TO_SERVER_STATICFILES it's not necessary``, because the schema name is automatically found for these actions.

.. code-block:: python

    # in settings.py

    # to work with schema_name_1 set:
    CURRENT_SCHEMA_TO_SERVER_STATICFILES = "schema_name_1"

    # change value to 'schema_name_2' for to work with other schema:
    CURRENT_SCHEMA_TO_SERVER_STATICFILES = "schema_name_2"

Static files aware tenant
-------------------------

.. code-block:: python

    STATICFILES_STORAGE = 'django_tenants.staticfiles.storage.TenantStaticFilesStorage'

``TenantStaticFilesStorage`` has the function of manipulating files of each tenant and collecting them to a specific directory of this tenant, having as destination directory: ``os.path.join (STATIC_ROOT, MULTITENANT_RELATIVE_STATIC_ROOT)``

The command to collect the static files of each tenant is ``collectstatic_schemas``

.. code-block:: bash

    ./manage.py collectstatic_schemas --schema=your_schema_name

For STATIC_ROOT settings with this value:

.. code-block:: python

    STATIC_ROOT = os.path.join (SITE_DIR, 'public', 'static')

We can set ``MULTITENANT_RELATIVE_STATIC_ROOT`` of the many ways, as bellow

Examples
~~~~~~~~

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_STATIC_ROOT = ""  # or not set

Static files will be collected at -> path_your_project/public/static/``tenant_name``.

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_STATIC_ROOT = "other_dir"

Static files will be collected at -> path_your_project/public/static/``other_dir/tenant_name``.

You can also use ``%s`` to have more freedom to manipulate the destination directory, where the ``%s`` will be replaced by the name of the ``schema``.

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_STATIC_ROOT = "%s/other_dir"

Static files will be collected at -> path_your_project/public/static/``tenant_name/other_dir``

Media files aware tenant
-------------------------

.. code-block:: python

    DEFAULT_FILE_STORAGE = 'django_tenants.files.storages.TenantFileSystemStorage'

``TenantFileSystemStorage`` has the function of uploading files of each tenant and put them to a specific directory of this tenant, having as destination directory: ``os.path.join (MEDIA_ROOT, MULTITENANT_RELATIVE_MEDIA_ROOT)``

For MEDIA_ROOT settings with this value:

.. code-block:: python

    MEDIA_ROOT = os.path.join (SITE_DIR, 'public', 'media')

We can set ``MULTITENANT_RELATIVE_MEDIA_ROOT`` of the many ways, as bellow

Examples
~~~~~~~~

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_MEDIA_ROOT = ""  # or not set

Media files will be uploaded at -> path_your_project/public/media/``tenant_name``.

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_MEDIA_ROOT = "other_dir"

Media files will be uploaded at -> path_your_project/public/media/``other_dir/tenant_name``.

You can also use ``%s`` to have more freedom to manipulate the upload destination directory, where the ``%s`` will be replaced by the name of the ``schema``.

.. code-block:: python

    # For:
    MULTITENANT_RELATIVE_MEDIA_ROOT = "%s/other_dir"

Media files will be uploaded at -> path_your_project/public/media/``tenant_name/other_dir``


text:
<?php

namespace Google\ApiCore\Tests\Unit\ResourceTemplate;

use Google\ApiCore\ResourceTemplate\AbsoluteResourceTemplate;
use Google\ApiCore\ValidationException;
use PHPUnit\Framework\TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectException;

class AbsoluteResourceTemplateTest extends TestCase
{
    use ExpectException;

    /**
     * @dataProvider validPathProvider
     * @param string $path
     * @param $expectedString
     */
    public function testValidPaths($path, $expectedString = null)
    {
        $template = new AbsoluteResourceTemplate($path);
        $this->assertEquals($expectedString ?: $path, $template->__toString());
    }

    public function validPathProvider()
    {
        return [
            ["/foo"],
            ["/*"],
            ["/**"],
            ["/{foo}", "/{foo=*}"],
            ["/{foo=*}"],
            ["/{foo=**}"],
            ["/foo/*"],
            ["/*/foo"],
            ["/foo/*:bar"],
            ["/*/foo:bar"],
            ["/*/*/*/*:foo"],
            ["/**/*/*:foo"],
            ["/foo/**/bar/*"],
            ["/foo/*/bar/**"],
            ["/foo/helloazAZ09-.~_what"],
        ];
    }

    /**
     * @dataProvider invalidPathProvider
     * @param string $path
     */
    public function testInvalidPaths($path)
    {
        $this->expectException(ValidationException::class);
        new AbsoluteResourceTemplate($path);
    }

    public function invalidPathProvider()
    {
        return [
            [""],                       // Empty path
            ["foo"],                    // No leading '/'
            ["/foo:bar/baz"],           // Action containing '/'
            ["/foo:bar:baz"],           // Multiple ':'
            ["/foo/bar*baz"],           // Mixed literal and '*'
            ["/foo/**/**"],             // Multiple '**'
            ["/foo/**/{var=**}"],       // Multiple '**' nested
            ["/foo/{bizz=**}/{var=**}"],// Multiple '**' nested
            ["/foo/{bizz=**/**}"],      // Multiple '**' nested
            ["/foo/{bar={baz}}"],       // Nested {}
            ["/foo/{bar=fizz=buzz}"],   // Multiple '=' in variable
            ["/foo/{bar"],              // Unmatched '{'
            ["/foo/{bar}/{bar}"],       // Duplicate variable key
            ["/foo/{bar/baz}"],         // Variable containing '/'
            ["/foo//bar"],              // Consecutive '/'
            ["//bar"],                  // Consecutive '/'
            ["/foo/"],                  // Trailing '/'
        ];
    }

    /**
     * @param string $pathTemplate
     * @param string $path
     * @param array $expectedBindings
     * @dataProvider matchData
     */
    public function testMatch($pathTemplate, $path, $expectedBindings)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);
        $this->assertEquals(
            $expectedBindings,
            $template->match($path)
        );
    }

    /**
     * @param string $pathTemplate
     * @param string $path
     * @dataProvider matchData
     */
    public function testMatches($pathTemplate, $path)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);
        $this->assertTrue($template->matches($path));
    }

    /**
     * @param string $pathTemplate
     * @param string $expectedPath
     * @param array $bindings
     * @dataProvider matchData
     */
    public function testRender($pathTemplate, $expectedPath, $bindings)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);
        $this->assertEquals($expectedPath, $template->render($bindings));
    }

    public function matchData()
    {
        return [
            [
                '/buckets/*/*/objects/*',
                '/buckets/f/o/objects/bar',
                ['$0' => 'f', '$1' => 'o', '$2' => 'bar'],
            ],
            [
                '/buckets/{hello}',
                '/buckets/world',
                ['hello' => 'world'],
            ],
            [
                '/buckets/{hello=*}',
                '/buckets/world',
                ['hello' => 'world'],
            ],
            [
                '/buckets/*:action',
                '/buckets/foo:action',
                ['$0' => 'foo'],
            ],
            [
                '/buckets/*/*/*/objects/*:action',
                '/buckets/f/o/o/objects/google.com:a-b:action',
                ['$0' => 'f', '$1' => 'o', '$2' => 'o', '$3' => 'google.com:a-b'],
            ],
            [
                '/buckets/*/objects/**:action',
                '/buckets/foo/objects/bar/baz:action',
                ['$0' => 'foo', '$1' => 'bar/baz'],
            ],
            [
                '/foo/*/{bar=*/rar/*}/**/*:action',
                '/foo/fizz/fuzz/rar/bar/bizz/buzz/baz:action',
                ['$0' => 'fizz', '$1' => 'bizz/buzz', '$2' => 'baz', 'bar' => 'fuzz/rar/bar'],
            ],
            [
                '/buckets/*',
                '/buckets/{}!@#$%^&*()+=[]\|`~-_',
                ['$0' => '{}!@#$%^&*()+=[]\|`~-_'],
            ],
        ];
    }

    /**
     * @param string $pathTemplate
     * @param string $path
     * @dataProvider invalidMatchData
     */
    public function testFailMatch($pathTemplate, $path)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);

        $this->expectException(ValidationException::class);

        $template->match($path);
    }

    /**
     * @param string $pathTemplate
     * @param string $path
     * @dataProvider invalidMatchData
     */
    public function testFailMatches($pathTemplate, $path)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);
        $this->assertFalse($template->matches($path));
    }

    public function invalidMatchData()
    {
        return [
            [
                '/buckets/*/*/objects/*',
                '/buckets/f/o/objects/bar/far', // Extra '/far'
            ],
            [
                '/buckets/*/*/objects/*',
                '/buckets/f/o/objects', // Missing final wildcard
            ],
            [
                '/foo/*/bar',
                '/foo/bar', // Missing middle wildcard
            ],
            [
                '/foo/*/bar',
                '/foo/fizz/buzz/bar', // Too many segments for middle wildcard
            ],
            [
                '/foo/**/bar',
                '/foo/bar', // Missing middle wildcard
            ],
            [
                '/buckets/*:action',
                '/buckets/foo', // Missing action
            ],
            [
                '/buckets/*:action',
                '/buckets/foo:actingout', // Wrong action
            ],
            [
                '/buckets/*:action',
                '/buckets/foo:actionstations', // Wrong action
            ],
            [
                '/buckets',
                '/bouquets', // Wrong literal
            ],
            [
                '/buckets',
                '/bucketseller', // Wrong literal
            ],
            [
                '/foo/*/{bar=*/rar/*}/**/*:action',
                '/foo/fizz/fuzz/rat/bar/bizz/buzz/baz:action',
            ],
        ];
    }

    /**
     * @param string $pathTemplate
     * @param array $bindings
     * @dataProvider invalidRenderData
     */
    public function testFailRender($pathTemplate, $bindings)
    {
        $template = new AbsoluteResourceTemplate($pathTemplate);

        $this->expectException(ValidationException::class);

        $template->render($bindings);
    }

    public function invalidRenderData()
    {
        return [
            [
                '/buckets/*/*/objects/*',
                ['$0' => 'f', '$2' => 'bar'], // Missing key
            ],
            [
                '/buckets/{hello}',
                ['hellop' => 'world'], // Wrong key
            ],
            [
                '/buckets/{hello=*}',
                ['hello' => 'world/weary'], // Invalid binding
            ],
            [
                '/buckets/{hello=*}',
                ['hello' => ''], // Invalid binding
            ],
            [
                '/buckets/*/objects/**:action',
                ['$0' => 'foo', '$1' => ''],  // Invalid binding
            ],
            [
                '/foo/*/{bar=*/rar/*}/**/*:action',
                ['$0' => 'fizz', '$1' => 'bizz/buzz', '$2' => 'baz', 'bar' => 'fuzz/rat/bar'],
                // Invalid binding
            ],
        ];
    }
}

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

  <meta charset="utf-8">
  <title>Sample Webpage</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="">
  <meta name="author" content="">
  <link rel="stylesheet" type="text/css" href="/styles/main.css">

						Hello, world!

						This is a sample website using the Heroku Multi Buildpack on Dokku. It uses the python, ruby, and node buildpacks. The node buildpack is for using bower and grunt. The ruby buildpack is for running compass. And last but not last, the python buildpack is to run the flask application.

						Learn more


text:
#include <CtrlLib/CtrlLib.h>
#include <RichEdit/RichEdit.h>
//#include <nmpTools/nmpTools.h>
#include <GridCtrl/GridCtrl.h>
#include <bigmailer/cfg.h>

#define LAYOUTFILE <bigmailer/bigmailer.lay>
#include <CtrlCore/lay.h>

#include <bigmailer/messages.h>

// Configuración
class cfgDlg : public WithCfgLayout<TopWindow> {
public:

	typedef cfgDlg CLASSNAME;

	cfgDlg();
	virtual ~cfgDlg();

	void onBtOK() ;

};

class bigmailer : public TopWindow { //public WithBigMailerLayout<TopWindow> {
	MenuBar mainMenu ;
	TabCtrl tab ;

	//MenuBar mainMenu ;
	void mnuMailAddr( Bar &bar ) ;
	void mnuMsg( Bar &bar ) ;
	void mnuSend( Bar &bar ) ;
	void mnuHelp( Bar &bar ) ;

	void onNewList() ;
	void onOpenList() ;
	void onCloseList() ;
	void onPrintList() ;
	void onExit() ;

	void onNewMsg() ; void onStart() ;
	void onOpenMsg() ;
	void onCloseMsg() ;
	void onPrintMsg() ;

	void onSend() ;

	void onPreferences() ;
	void onAbout() ;

	int lastTabIndex ;
	void onTabSet() ;

	// Páginas
	WithListDataLayout<ParentCtrl> dataPage ;
		EditString dataPage_theEdits[30], dataPage_editError ;
		void DataPageFill() ;
		void DataPageSave() ;
		void DataPageTheGridModification() ;
		void DataPageEditFields() ;
		void DataPageImportCSV() ;

	MessageEditor messagePage ;

	static bigmailer *mailer ;
public:
	static bigmailer& Mailer() { return *mailer ; }
	void SetTitle() ;

	typedef bigmailer CLASSNAME;
	bigmailer();
};

#endif


text:
package za.co.luma.math.function;

/**
 * This class is sued to create 2D Perlin noise.
 *
 * @author Herman Tulleken
 *
 */
public class PerlinFunction2D extends RealFunction2D
{
	private static final double DEFAULT_PERSISTANCE = 0.9;

	private final int octaves;

	private SmoothNoise2D[] textures;
	double persistence;
	int samplingPeriodMax;
	boolean normalize;

	public PerlinFunction2D(int width, int height, int octaves)
	{
		this(width, height, octaves, DEFAULT_PERSISTANCE, true);
	}

	public PerlinFunction2D(int width, int height, int octaves, double persistence, boolean normalize)
	{

		this.octaves = octaves;
		textures = new SmoothNoise2D[octaves];
		samplingPeriodMax = 1 << octaves;
		//samplingPeriodMax = width >> octaves;
		this.persistence = persistence;
		this.normalize = normalize;

		for (int i = 0; i < octaves; i++)
		{
			textures[i] = new SmoothNoise2D(width + samplingPeriodMax + 1, height + samplingPeriodMax + 1);
		}
	}

	@Override
	public double getDouble(int u, int v)
	{
		double amplitude = 1.0;
		double totalAmplitude = 0.0;
		double col = 0;
		int samplingPeriod = samplingPeriodMax;

		for (int i = 0; i < octaves; i++)
		{
			amplitude *= persistence;
			totalAmplitude += amplitude;
			col += (textures[i].getNoise(u, v, samplingPeriod)) * amplitude;
			samplingPeriod /= 2;
		}

		if (normalize)
		{
			col /= totalAmplitude;
		}
		else //clamp
		{
			if (col > 1.0)
			{
				col = 1.0;
			}
			else if (col < 0.0)
			{
				col = 0.0;
			}
		}

		return col;
	}
}


text:
import sublime_plugin

from functools import partial

from ..anaconda_lib.worker import Worker
from ..anaconda_lib.helpers import prepare_send_data, is_python, get_settings

class AnacondaSignaturesEventListener(sublime_plugin.EventListener):
    """Signatures on status bar event listener class
    """

    documentation = None
    exclude = (
        'None', 'str', 'int', 'float', 'True', 'False', 'in', 'or', 'and')

    def on_modified(self, view):
        """Called after changes has been made to a view
        """

        if not is_python(view) or not get_settings(view, 'display_signatures'):
            return

        try:
            location = view.rowcol(view.sel()[0].begin())
            if view.substr(view.sel()[0].begin()) in ['(', ')']:
                location = (location[0], location[1] - 1)

            data = prepare_send_data(location, 'doc', 'jedi')
            Worker().execute(partial(self.prepare_data, view), **data)
        except Exception as error:
            print(error)

    def prepare_data(self, view, data):
        """Prepare the returned data
        """

        if data['success'] and 'No docstring' not in data['doc']:
            self.documentation = data['doc'].splitlines()[2]
            if self.documentation.split('(')[0] not in self.exclude:
                if self.documentation is not None and self.documentation != '':
                    self._show_status(view)
                    return

        view.erase_status('anaconda_doc')

    def _show_status(self, view):
        """Show message in the view status bar
        """

        view.set_status(
            'anaconda_doc', 'Anaconda: {}'.format(self.documentation)
        )


text:
[![Build Status](https://travis-ci.org/cbus-sea-lions-2015/DEVOLIO.svg?branch=master)](https://travis-ci.org/cbus-sea-lions-2015/DEVOLIO) | [![Coverage Status](https://coveralls.io/repos/cbus-sea-lions-2015/DEVOLIO/badge.svg)](https://coveralls.io/r/cbus-sea-lions-2015/DEVOLIO)

Build yo dev portfolio! Brought to you by The Architects, DevBootcamp students in the Columbus, Ohio Localhost pilot program.

[Jonathan Roger](https://github.com/jroger2908) | [Mary Baylis](https://github.com/MaryCBaylis) | [Chris Singer](https://github.com/secade) | [Jan Dennison](https://github.com/jannypie)

---
The dev community often focuses less on traditional resumes and more on GitHub activity and project experience. However, HR departments and recruiters are still oriented towards the formal resume model. And look, searching for a job is a hard thing in general - juggling different information and audiences shouldn't be part of it.

*DEVOLIO* merges LinkedIn resume information with your GitHub account activity to quickly and easily produce an attractive, informative job search profile. Additionally, the dev community is centralized around Twitter, so you can also show your Twitter stream and have it curated to only bring in specific keywords. Check it out!

---

[Project Goals](#goals) | [Technologies](#tech) | [Visual Guide](#visual) | [Wireframes](#wireframes)

---

## Project Goals
- Complete MVP is important
- 80% minimum test coverage, attempt TDD for portions
- Responsive front end for sharing on mobile devices
- Continuous integration and automated deployment

### Group goals
- Honest and timely feedback and communication among group members
- Ask for help when stuck (err on the side of asking)
- Flexible workflows: pairing and individual, mix it up
- Support working from homes at least one day over the weekend
- Flexible on working early vs working late (asyncronously)
- Sunday afternoon off, Team Retro #1 on Sunday evening

### User Stories
As a DevRes Builder user, I want to:
- Create an account, Edit, Delete
- Sign in / sign out
- Connect my GitHub account
  - Twitter
  - LinkedIn
- Have a public-facing profile resume built (/username)
- Import/Display my (curated) recent Tweets
- Import/Display my (curated) Github/LinkedIn information

### MVP Goals
- Meet user story features

### Stretch Goals
- See Google Analytics statistics on my public profile
- Multiple Resumes
- Additional service API integration
  - CodePen
  - Dribbble
- Custom URL (default to username)
- Export to PDF
- Printable CSS
- Email integration

## Technologies
- Ruby on Rails with ~~Postgres~~ MongoDB
- MongoDB, managed through Mongoid ODM library
- Backbone.JS for front-end MVC
- RSpec testing on Ruby
- Jasmine testing on front end
- Responsive Bootstrap framework, customized
- CSS/Sass
- Team communication through Slack
- Project management through Trello

### Tech Spikes
Technologies to research for the project:
- APIs
  - Google Analytics
  - GitHub
  - Twitter
  - LinkedIn
- Stacks
  - AWS
- Client-side JS Frameworks
  - Backbone
  - Angular
  - Meteor
- Testing
  - Cucumber
- Other
  - Devise
  - D3
  - Octokit
- Added
  - MongoDB, MongoID

## Visual Guide
Colors, fonts, general idea gathering.
![Visual Guide](visual-guides/devolio-visual-guide.jpg)

## Wireframes
Overall direction of UI design.

Index
![Wireframe](visual-guides/devolio-wireframe-home.jpg)

User Dashboard: Option 1
![Wireframe](visual-guides/devolio-wireframe-dashboard.jpg)

User Dashboard: Option 2
![Wireframe](visual-guides/devolio-wireframe-dashboard-2.jpg)

User public profile
![Wireframe](visual-guides/devolio-wireframe-profile.jpg)

User public profile mockup
![mockup](visual-guides/devolio-public-page-wireframe.jpg)


text:
function __processArg(obj, key) {
    var arg = null;
    if (obj) {
        arg = obj[key] || null;
        delete obj[key];
    }
    return arg;
}

function Controller() {
    function __alloyId21() {
        $.__views.index.removeEventListener("open", __alloyId21);
        if ($.__views.index.activity) ; else {
            Ti.API.warn("You attempted to access an Activity on a lightweight Window or other");
            Ti.API.warn("UI component which does not have an Android activity. Android Activities");
            Ti.API.warn("are valid with only windows in TabGroups or heavyweight Windows.");
        }
    }
    function __alloyId25() {
        $.__views.index.removeEventListener("open", __alloyId25);
        if ($.__views.index.activity) $.__views.index.activity.onCreateOptionsMenu = function(e) {
            var __alloyId24 = {
                title: "Settings",
                icon: "/images/overflow.png",
                showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM,
                id: "__alloyId23"
            };
            $.__views.__alloyId23 = e.menu.add(_.pick(__alloyId24, Alloy.Android.menuItemCreateArgs));
            $.__views.__alloyId23.applyProperties(_.omit(__alloyId24, Alloy.Android.menuItemCreateArgs));
            clickedSettings ? $.__views.__alloyId23.addEventListener("click", clickedSettings) : __defers["$.__views.__alloyId23!click!clickedSettings"] = true;
        }; else {
            Ti.API.warn("You attempted to attach an Android Menu to a lightweight Window");
            Ti.API.warn("or other UI component which does not have an Android activity.");
            Ti.API.warn("Android Menus can only be opened on TabGroups and heavyweight Windows.");
        }
    }
    function clickedSettings() {
        var settingsController = Alloy.createController("settings");
        var win = settingsController.getView();
        Alloy.Globals.navgroup ? Alloy.Globals.navgroup.openWindow(win) : win.open();
    }
    function calendar() {
        Alloy.createController("calendar").getView();
    }
    function contactUs() {
        Alloy.createController("contact").getView();
    }
    function deviceTokenSuccess(e) {
        alert("please work" + e.deviceToken);
        deviceToken = e.deviceToken;
        subscribeToChannel(deviceToken);
    }
    function deviceTokenError(e) {
        alert("Failed to register for push notifications! " + e.error);
    }
    function subscribeToChannel(deviceToken) {
        Cloud.PushNotifications.subscribeToken({
            device_token: deviceToken,
            channel: "news_alerts",
            type: "android"
        }, function(e) {
            alert(e.success ? "Subscribed" : "Error:\n" + (e.error && e.message || JSON.stringify(e)));
        });
    }
    require("alloy/controllers/BaseController").apply(this, Array.prototype.slice.call(arguments));
    this.__controllerPath = "index";
    if (arguments[0]) {
        {
            __processArg(arguments[0], "__parentSymbol");
        }
        {
            __processArg(arguments[0], "$model");
        }
        {
            __processArg(arguments[0], "__itemTemplate");
        }
    }
    var $ = this;
    var exports = {};
    var __defers = {};
    $.__views.index = Ti.UI.createWindow({
        backgroundColor: "#222222",
        id: "index"
    });
    $.__views.index && $.addTopLevelView($.__views.index);
    $.__views.index.addEventListener("open", __alloyId21);
    $.__views.index.addEventListener("open", __alloyId25);
    $.__views.corn = Ti.UI.createImageView({
        top: "5%",
        width: 195,
        height: 265,
        id: "corn",
        image: "/images/logo.png"
    });
    $.__views.index.add($.__views.corn);
    $.__views.cobButton = Ti.UI.createButton({
        width: 65,
        height: 65,
        top: "50%",
        left: "10%",
        backgroundImage: "/images/browser.png",
        id: "cobButton"
    });
    $.__views.index.add($.__views.cobButton);
    $.__views.calendarButton = Ti.UI.createButton({
        width: 65,
        height: 65,
        top: "50%",
        backgroundImage: "/images/calendar.png",
        id: "calendarButton"
    });
    $.__views.index.add($.__views.calendarButton);
    calendar ? $.__views.calendarButton.addEventListener("click", calendar) : __defers["$.__views.calendarButton!click!calendar"] = true;
    $.__views.contactButton = Ti.UI.createButton({
        width: 65,
        height: 65,
        top: "50%",
        right: "10%",
        backgroundImage: "/images/contact.png",
        id: "contactButton"
    });
    $.__views.index.add($.__views.contactButton);
    contactUs ? $.__views.contactButton.addEventListener("click", contactUs) : __defers["$.__views.contactButton!click!contactUs"] = true;
    $.__views.facebookButton = Ti.UI.createButton({
        width: 65,
        height: 65,
        top: "75%",
        left: "25%",
        backgroundImage: "/images/facebook.png",
        id: "facebookButton"
    });
    $.__views.index.add($.__views.facebookButton);
    $.__views.youtubeButton = Ti.UI.createButton({
        width: 65,
        height: 65,
        top: "75%",
        right: "25%",
        backgroundImage: "/images/youtube.png",
        id: "youtubeButton"
    });
    $.__views.index.add($.__views.youtubeButton);
    exports.destroy = function() {};
    _.extend($, $.__views);
    arguments[0] || {};
    $.cobButton.addEventListener("click", function() {
        Ti.Platform.openURL("http://www.wtamu.edu/academics/college-business.aspx");
    });
    $.facebookButton.addEventListener("click", function() {
        Ti.Platform.openURL("http://www.facebook.com/WTAMUCOB");
    });
    $.youtubeButton.addEventListener("click", function() {
        Ti.Platform.openURL("https://www.youtube.com/channel/UCENCoEEcsLJvyWaMjonwFuQ");
    });
    var CloudPush = require("ti.cloudpush");
    var Cloud = require("ti.cloud");
    var deviceToken = null;
    CloudPush.retrieveDeviceToken({
        success: deviceTokenSuccess,
        error: deviceTokenError
    });
    CloudPush.addEventListener("callback", function(evt) {
        alert("Notification received: " + evt.payload);
    });
    $.index.open();
    __defers["$.__views.__alloyId23!click!clickedSettings"] && $.__views.__alloyId23.addEventListener("click", clickedSettings);
    __defers["$.__views.calendarButton!click!calendar"] && $.__views.calendarButton.addEventListener("click", calendar);
    __defers["$.__views.contactButton!click!contactUs"] && $.__views.contactButton.addEventListener("click", contactUs);
    _.extend($, exports);
}

var Alloy = require("alloy"), Backbone = Alloy.Backbone, _ = Alloy._;

module.exports = Controller;


text:
package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/engine/standard"
	"github.com/webx-top/echo/handler/pprof"
	"github.com/webx-top/echo/middleware/ratelimiter"
	"github.com/webx-top/echo/testing"
	"gopkg.in/redis.v5"
)

// RedisClient Implements RedisClient for redis.Client
type RedisClient struct {
	*redis.Client
}

func (c *RedisClient) DeleteKey(key string) error {
	return c.Del(key).Err()
}

func (c *RedisClient) EvalulateSha(sha1 string, keys []string, args ...interface{}) (interface{}, error) {
	return c.EvalSha(sha1, keys, args...).Result()
}

func (c *RedisClient) LuaScriptLoad(script string) (string, error) {
	return c.ScriptLoad(script).Result()
}

func main() {
	e := echo.New()
	e.Get("/", echo.HandlerFunc(func(c echo.Context) error {
		return c.String("Hello, World!")
	}), ratelimiter.RateLimiterWithConfig(ratelimiter.RateLimiterConfig{
		Max:      5,
		Duration: time.Second,
	}))
	redisDisabled := false
	if !redisDisabled {

		var client = redis.NewClient(&redis.Options{
			Addr: `127.0.0.1:6379`,
		})
		defer client.Close()
		e.Get("/redis", echo.HandlerFunc(func(c echo.Context) error {
			return c.String("Hello, World!")
		}), ratelimiter.RateLimiterWithConfig(ratelimiter.RateLimiterConfig{
			Max:      5,
			Duration: time.Second,
			Client:   &RedisClient{Client: client},
		}))

	}

	pprof.Wrap(e)

	go e.Run(standard.New(":4444"))

	time.Sleep(time.Second * 2)
	var codes []int
	wg := sync.WaitGroup{}
	for i := 0; i < 200; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			rec := testing.Request(`GET`, `/redis`, e)
			after := rec.Header().Get(`X-Retry-After`)
			if len(after) > 0 {
				fmt.Println(`X-Retry-After:`, after)
				m, err := time.ParseDuration(after)
				if err != nil {
					fmt.Println(err)
				} else {
					//time.Sleep(m + time.Millisecond)
					time.Sleep(m + time.Second)
				}
			}
			codes = append(codes, rec.Code)
		}()
	}
	wg.Wait()
	echo.Dump(codes)

	<-make(chan struct{})
}


text:
#include "EnvisionApplication.h"
#include "EnvisionManager.h"

namespace Core {

QMap<void*, EnvisionApplication::IdleFunction>& EnvisionApplication::idleActions()
{
	static QMap<void*, EnvisionApplication::IdleFunction> actions;
	return actions;
}

EnvisionApplication::EnvisionApplication(int& argc, char** argv) : QApplication(argc, argv)
{
	idleInputTimer_.setInterval(50);
	idleInputTimer_.setSingleShot(true);
	connect(&idleInputTimer_, SIGNAL(timeout()), this, SLOT(userInputIdle()));
}

bool EnvisionApplication::notify(QObject* receiver, QEvent* event)
{
	if (	event->spontaneous()) idleInputTimer_.start();

	EnvisionManager::processPreEventActions(receiver, event);
	auto res = QApplication::notify(receiver, event);
	EnvisionManager::processPostEventActions(receiver, event);
	return res;
}

void EnvisionApplication::addOnUserInputIdleAction(void* actionId, IdleFunction action)
{
	idleActions().insert(actionId, action);
}

void EnvisionApplication::removeOnUserInputIdleAction(void* actionId)
{
	idleActions().remove(actionId);
}

void EnvisionApplication::userInputIdle()
{
	for (auto& a : idleActions().values()) a();
}

} /* namespace Core */


text:
<?php
namespace Concrete\Core\Filesystem\FileLocator;

use Concrete\Core\Package\PackageList;
use Concrete\Core\Page\Theme\Theme;
use Illuminate\Filesystem\Filesystem;

class ThemeElementLocation extends ThemeLocation
{

    public function getPath()
    {
        if ($this->pkgHandle) {
            return DIR_PACKAGES
                . DIRECTORY_SEPARATOR
                . $this->pkgHandle
                . DIRECTORY_SEPARATOR
                . DIRNAME_THEMES
                . DIRECTORY_SEPARATOR
                . $this->themeHandle
                . DIRECTORY_SEPARATOR
                . DIRNAME_ELEMENTS
                . DIRECTORY_SEPARATOR
                . 'concrete';
        } else {
            return DIR_APPLICATION
                . DIRECTORY_SEPARATOR
                . DIRNAME_THEMES
                . DIRECTORY_SEPARATOR
                . $this->themeHandle
                . DIRECTORY_SEPARATOR
                . DIRNAME_ELEMENTS
                . DIRECTORY_SEPARATOR
                . 'concrete';
        }
    }

    public function contains($file)
    {
        // Since we are testing this in a special way, we strip DIRNAME_ELEMENTS off the front.
        $length = strlen(DIRNAME_ELEMENTS . DIRECTORY_SEPARATOR);
        $file = substr($file, $length);
        return parent::contains($file);
    }

    public function getURL()
    {
        if ($this->pkgHandle) {
            return DIR_REL
            . DIRECTORY_SEPARATOR
            . $this->pkgHandle
            . DIRECTORY_SEPARATOR
            . DIRNAME_THEMES
            . DIRECTORY_SEPARATOR
            . $this->themeHandle
            . DIRECTORY_SEPARATOR
            . DIRNAME_ELEMENTS
            . DIRECTORY_SEPARATOR
            . 'concrete';
        } else {
            return DIR_REL
            . DIRECTORY_SEPARATOR
            . DIRNAME_THEMES
            . DIRECTORY_SEPARATOR
            . $this->themeHandle
            . DIRECTORY_SEPARATOR
            . DIRNAME_ELEMENTS
            . DIRECTORY_SEPARATOR
            . 'concrete';
        }
    }
}


text:
// Vex Flow
// Mohit Muthanna <mohit@muthanna.com>
//
// Copyright Mohit Cheppudira 2010

/** @constructor */
Vex.Flow.Stave = (function() {
  function Stave(x, y, width, options) {
    if (arguments.length > 0) this.init(x, y, width, options);
  }

  var THICKNESS = (Vex.Flow.STAVE_LINE_THICKNESS > 1 ?
        Vex.Flow.STAVE_LINE_THICKNESS : 0);
  Stave.prototype = {
    init: function(x, y, width, options) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.glyph_start_x = x + 5;
      this.glyph_end_x = x + width;
      this.start_x = this.glyph_start_x;
      this.end_x = this.glyph_end_x;
      this.context = null;
      this.glyphs = [];
      this.end_glyphs = [];
      this.modifiers = [];  // non-glyph stave items (barlines, coda, segno, etc.)
      this.measure = 0;
      this.clef = "treble";
      this.font = {
        family: "sans-serif",
        size: 8,
        weight: ""
      };
      this.options = {
        vertical_bar_width: 10,       // Width around vertical bar end-marker
        glyph_spacing_px: 10,
        num_lines: 5,
        fill_style: "#999999",
        spacing_between_lines_px: 10, // in pixels
        space_above_staff_ln: 4,      // in staff lines
        space_below_staff_ln: 4,      // in staff lines
        top_text_position: 1          // in staff lines
      };
      this.bounds = {x: this.x, y: this.y, w: this.width, h: 0};
      Vex.Merge(this.options, options);

      this.resetLines();

      this.modifiers.push(
          new Vex.Flow.Barline(Vex.Flow.Barline.type.SINGLE, this.x)); // beg bar
      this.modifiers.push(
          new Vex.Flow.Barline(Vex.Flow.Barline.type.SINGLE,
          this.x + this.width)); // end bar
    },

    resetLines: function() {
      this.options.line_config = [];
      for (var i = 0; i < this.options.num_lines; i++) {
        this.options.line_config.push({visible: true});
      }
      this.height = (this.options.num_lines + this.options.space_above_staff_ln) *
         this.options.spacing_between_lines_px;
      this.options.bottom_text_position = this.options.num_lines + 1;
    },

    setNoteStartX: function(x) { this.start_x = x; return this; },
    getNoteStartX: function() {
      var start_x = this.start_x;

      // Add additional space if left barline is REPEAT_BEGIN and there are other
      // start modifiers than barlines
      if (this.modifiers[0].barline == Vex.Flow.Barline.type.REPEAT_BEGIN &&
          this.modifiers.length > 2)
        start_x += 20;
      return start_x;
    },

    getNoteEndX: function() { return this.end_x; },
    getTieStartX: function() { return this.start_x; },
    getTieEndX: function() { return this.x + this.width; },
    setContext: function(context) { this.context = context; return this; },
    getContext: function() { return this.context; },
    getX: function() { return this.x; },
    getNumLines: function() { return this.options.num_lines; },
    setNumLines: function(lines) {
      this.options.num_lines = parseInt(lines, 10);
      this.resetLines();
      return this;
    },
    setY: function(y) { this.y = y; return this; },

    setWidth: function(width) {
      this.width = width;
      this.glyph_end_x = this.x + width;
      this.end_x = this.glyph_end_x;

      // reset the x position of the end barline
      this.modifiers[1].setX(this.end_x);
      return this;
    },

    getWidth: function() {
      return this.width;
    },

    setMeasure: function(measure) { this.measure = measure; return this; },

      // Bar Line functions
    setBegBarType: function(type) {
      // Only valid bar types at beginning of stave is none, single or begin repeat
      if (type == Vex.Flow.Barline.type.SINGLE ||
          type == Vex.Flow.Barline.type.REPEAT_BEGIN ||
          type == Vex.Flow.Barline.type.NONE) {
          this.modifiers[0] = new Vex.Flow.Barline(type, this.x);
      }
      return this;
    },

    setEndBarType: function(type) {
      // Repeat end not valid at end of stave
      if (type != Vex.Flow.Barline.type.REPEAT_BEGIN)
        this.modifiers[1] = new Vex.Flow.Barline(type, this.x + this.width);
      return this;
    },

    /**
     * Gets the pixels to shift from the beginning of the stave
     * following the modifier at the provided index
     * @param  {Number} index The index from which to determine the shift
     * @return {Number}       The amount of pixels shifted
     */
    getModifierXShift: function(index) {
      if (typeof index === 'undefined') index = this.glyphs.length -1;
      if (typeof index !== 'number') new Vex.RERR("InvalidIndex",
        "Must be of number type");

      var x = this.glyph_start_x;
      var bar_x_shift = 0;

      for (var i = 0; i < index + 1; ++i) {
        var glyph = this.glyphs[i];
        x += glyph.getMetrics().width;
        bar_x_shift += glyph.getMetrics().width;
      }

      // Add padding after clef, time sig, key sig
      if (bar_x_shift > 0) bar_x_shift += this.options.vertical_bar_width + 10;

      return bar_x_shift;
    },

    // Coda & Segno Symbol functions
    setRepetitionTypeLeft: function(type, y) {
      this.modifiers.push(new Vex.Flow.Repetition(type, this.x, y));
      return this;
    },

    setRepetitionTypeRight: function(type, y) {
      this.modifiers.push(new Vex.Flow.Repetition(type, this.x, y) );
      return this;
    },

    // Volta functions
    setVoltaType: function(type, number_t, y) {
      this.modifiers.push(new Vex.Flow.Volta(type, number_t, this.x, y));
      return this;
    },

    // Section functions
    setSection: function(section, y) {
      this.modifiers.push(new Vex.Flow.StaveSection(section, this.x, y));
      return this;
    },

    // Tempo functions
    setTempo: function(tempo, y) {
      this.modifiers.push(new Vex.Flow.StaveTempo(tempo, this.x, y));
      return this;
    },

    // Text functions
    setText: function(text, position, options) {
      this.modifiers.push(new Vex.Flow.StaveText(text, position, options));
      return this;
    },

    getHeight: function() {
      return this.height;
    },

    getSpacingBetweenLines: function() {
      return this.options.spacing_between_lines_px;
    },

    getBoundingBox: function() {
      return new Vex.Flow.BoundingBox(this.x, this.y, this.width, this.getBottomY() - this.y);
      // body...
    },

    getBottomY: function() {
      var options = this.options;
      var spacing = options.spacing_between_lines_px;
      var score_bottom = this.getYForLine(options.num_lines) +
         (options.space_below_staff_ln * spacing);

      return score_bottom;
    },

    getBottomLineY: function() {
      return this.getYForLine(this.options.num_lines);
    },

    getYForLine: function(line) {
      var options = this.options;
      var spacing = options.spacing_between_lines_px;
      var headroom = options.space_above_staff_ln;

      var y = this.y + ((line * spacing) + (headroom * spacing)) -
        (THICKNESS / 2);

      return y;
    },

    getYForTopText: function(line) {
      var l = line || 0;
      return this.getYForLine(-l - this.options.top_text_position);
    },

    getYForBottomText: function(line) {
      var l = line || 0;
      return this.getYForLine(this.options.bottom_text_position + l);
    },

    getYForNote: function(line) {
      var options = this.options;
      var spacing = options.spacing_between_lines_px;
      var headroom = options.space_above_staff_ln;
      var y = this.y + (headroom * spacing) + (5 * spacing) - (line * spacing);

      return y;
    },

    getYForGlyphs: function() {
      return this.getYForLine(3);
    },

    addGlyph: function(glyph) {
      glyph.setStave(this);
      this.glyphs.push(glyph);
      this.start_x += glyph.getMetrics().width;
      return this;
    },

    addEndGlyph: function(glyph) {
      glyph.setStave(this);
      this.end_glyphs.push(glyph);
      this.end_x -= glyph.getMetrics().width;
      return this;
    },

    addModifier: function(modifier) {
      this.modifiers.push(modifier);
      modifier.addToStave(this, (this.glyphs.length === 0));
      return this;
    },

    addEndModifier: function(modifier) {
      this.modifiers.push(modifier);
      modifier.addToStaveEnd(this, (this.end_glyphs.length === 0));
      return this;
    },

    addKeySignature: function(keySpec) {
      this.addModifier(new Vex.Flow.KeySignature(keySpec));
      return this;
    },

    addClef: function(clef, size, annotation) {
      this.clef = clef;
      this.addModifier(new Vex.Flow.Clef(clef, size, annotation));
      return this;
    },

    addEndClef: function(clef, size, annotation) {
      this.addEndModifier(new Vex.Flow.Clef(clef, size, annotation));
      return this;
    },

    addTimeSignature: function(timeSpec, customPadding) {
      this.addModifier(new Vex.Flow.TimeSignature(timeSpec, customPadding));
      return this;
    },

    addEndTimeSignature: function(timeSpec, customPadding) {
      this.addEndModifier(new Vex.Flow.TimeSignature(timeSpec, customPadding));
    },

    addTrebleGlyph: function() {
      this.clef = "treble";
      this.addGlyph(new Vex.Flow.Glyph("v83", 40));
      return this;
    },

    /**
     * All drawing functions below need the context to be set.
     */
    draw: function() {
      if (!this.context) throw new Vex.RERR("NoCanvasContext",
          "Can't draw stave without canvas context.");

      var num_lines = this.options.num_lines;
      var width = this.width;
      var x = this.x;
      var y;
      var glyph;

      // Render lines
      for (var line=0; line < num_lines; line++) {
        y = this.getYForLine(line);

        this.context.save();
        this.context.setFillStyle(this.options.fill_style);
        this.context.setStrokeStyle(this.options.fill_style);
        if (this.options.line_config[line].visible) {
          this.context.fillRect(x, y, width, Vex.Flow.STAVE_LINE_THICKNESS);
        }
        this.context.restore();
      }

      // Render glyphs
      x = this.glyph_start_x;
      for (var i = 0; i < this.glyphs.length; ++i) {
        glyph = this.glyphs[i];
        if (!glyph.getContext()) {
          glyph.setContext(this.context);
        }
        glyph.renderToStave(x);
        x += glyph.getMetrics().width;
      }

      // Render end glyphs
      x = this.glyph_end_x;
      for (i = 0; i < this.end_glyphs.length; ++i) {
        glyph = this.end_glyphs[i];
        if (!glyph.getContext()) {
          glyph.setContext(this.context);
        }
        x -= glyph.getMetrics().width;
        glyph.renderToStave(x);
      }

      // Draw the modifiers (bar lines, coda, segno, repeat brackets, etc.)
      for (i = 0; i < this.modifiers.length; i++) {
        // Only draw modifier if it has a draw function
        if (typeof this.modifiers[i].draw == "function")
          this.modifiers[i].draw(this, this.getModifierXShift());
      }

      // Render measure numbers
      if (this.measure > 0) {
        this.context.save();
        this.context.setFont(this.font.family, this.font.size, this.font.weight);
        var text_width = this.context.measureText("" + this.measure).width;
        y = this.getYForTopText(0) + 3;
        this.context.fillText("" + this.measure, this.x - text_width / 2, y);
        this.context.restore();
      }

      return this;
    },

    // Draw Simple barlines for backward compatability
    // Do not delete - draws the beginning bar of the stave
    drawVertical: function(x, isDouble) {
      this.drawVerticalFixed(this.x + x, isDouble);
    },

    drawVerticalFixed: function(x, isDouble) {
      if (!this.context) throw new Vex.RERR("NoCanvasContext",
          "Can't draw stave without canvas context.");

      var top_line = this.getYForLine(0);
      var bottom_line = this.getYForLine(this.options.num_lines - 1);
      if (isDouble)
        this.context.fillRect(x - 3, top_line, 1, bottom_line - top_line + 1);
      this.context.fillRect(x, top_line, 1, bottom_line - top_line + 1);
    },

    drawVerticalBar: function(x) {
      this.drawVerticalBarFixed(this.x + x, false);
    },

    drawVerticalBarFixed: function(x) {
      if (!this.context) throw new Vex.RERR("NoCanvasContext",
          "Can't draw stave without canvas context.");

      var top_line = this.getYForLine(0);
      var bottom_line = this.getYForLine(this.options.num_lines - 1);
      this.context.fillRect(x, top_line, 1, bottom_line - top_line + 1);
    },

    /**
     * Get the current configuration for the Stave.
     * @return {Array} An array of configuration objects.
     */
    getConfigForLines: function() {
      return this.options.line_config;
    },

    /**
     * Configure properties of the lines in the Stave
     * @param line_number The index of the line to configure.
     * @param line_config An configuration object for the specified line.
     * @throws Vex.RERR "StaveConfigError" When the specified line number is out of
     *   range of the number of lines specified in the constructor.
     */
    setConfigForLine: function(line_number, line_config) {
      if (line_number >= this.options.num_lines || line_number < 0) {
        throw new Vex.RERR("StaveConfigError",
          "The line number must be within the range of the number of lines in the Stave.");
      }
      if (!line_config.hasOwnProperty('visible')) {
        throw new Vex.RERR("StaveConfigError",
          "The line configuration object is missing the 'visible' property.");
      }
      if (typeof(line_config.visible) !== 'boolean') {
        throw new Vex.RERR("StaveConfigError",
          "The line configuration objects 'visible' property must be true or false.");
      }

      this.options.line_config[line_number] = line_config;

      return this;
    },

    /**
     * Set the staff line configuration array for all of the lines at once.
     * @param lines_configuration An array of line configuration objects.  These objects
     *   are of the same format as the single one passed in to setLineConfiguration().
     *   The caller can set null for any line config entry if it is desired that the default be used
     * @throws Vex.RERR "StaveConfigError" When the lines_configuration array does not have
     *   exactly the same number of elements as the num_lines configuration object set in
     *   the constructor.
     */
    setConfigForLines: function(lines_configuration) {
      if (lines_configuration.length !== this.options.num_lines) {
        throw new Vex.RERR("StaveConfigError",
          "The length of the lines configuration array must match the number of lines in the Stave");
      }

      // Make sure the defaults are present in case an incomplete set of
      //  configuration options were supplied.
      for (var line_config in lines_configuration) {
        // Allow 'null' to be used if the caller just wants the default for a particular node.
        if (!lines_configuration[line_config]) {
          lines_configuration[line_config] = this.options.line_config[line_config];
        }
        Vex.Merge(this.options.line_config[line_config], lines_configuration[line_config]);
      }

      this.options.line_config = lines_configuration;

      return this;
    }
  };

  return Stave;
}());