<commit_before>var DefaultAttributeLocationBinding = require('./ProgramAttributeLocationBinding');

//TODO: this is true in 99% of cases, might be implementation specific
var NUM_VERTEX_ATTRIBUTES_MAX = 16;

var STR_ERROR_UNIFORM_UNDEFINED = 'Uniform "%s" is not defined.';
var STR_ERROR_WRONG_NUM_ARGS = 'Wrong number of arguments.';
var STR_ERROR_INVALID_UNIFORM_TYPE = 'Unsupported uniform type "%s".';
var STR_ERROR_ATTRIBUTE_BINDING_UNDEFINED = 'Attribute "%s" is not present in program.';

function Program(context, vertSrc, fragSrc, attributeLocationBinding){
    var gl = this._gl = context.getGL();

    this._handle           = gl.createProgram();
    this._attributes       = {};
    this._uniforms         = {};
    this._uniformSetterMap = {};
    if(vertSrc){
        this.update(vertSrc, fragSrc, attributeLocationBinding);
    }
}

Program.prototype.getHandle = function(){
    return this._handle;
};

Program.prototype._bindInternal = function(){
    this._gl.useProgram(this._handle);
};

/**
 * updates shaders sources and links the program
 * @param  {String} vertSrc                 - vert shader source (or combined vert/fragShader)
 * @param  {String} [fragSrc]               - frag shader source
 * @param  {String} [attributeLocationBinding] - attribute locations map { 0: 'aPositon', 1: 'aNormal', 2: 'aColor' }
 */
Program.prototype.update = function(vertSrc, fragSrc, attributeLocationBinding){
    var gl = this._gl;
    var program = this._handle;

    var vertShader = this._compileSource(gl.VERTEX_SHADER, vertSrc);
    var fragShader = this._compileSource(gl.FRAGMENT_SHADER, fragSrc);

    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);

    for(var location = 0; location < NUM_VERTEX_ATTRIBUTES_MAX; location++){
        var attributeName = (attributeLocationBinding && attributeLocationBinding[location]) || DefaultAttributeLocationBinding[location];
        gl.bindAttribLocation(program, location, attributeName);
    }

    gl.linkProgram(program);

    if(!gl.getProgramParameter(program, gl.LINK_STATUS)){
        throw new Error('PROGRAM: ' + gl.getProgramInfoLog(program));
    }

    //Mark for deletion, they are not actually deleted until you call deleteProgram() in dispose()
    gl.deleteShader(vertShader);
    gl.deleteShader(fragShader);

    this._updateUniforms();
    this._updateAttributes();

    for(var location in attributeLocationBinding){
        var attributeName = attributeLocationBinding[location];
        if(this._attributes[attributeName] === undefined){
            throw new Error(STR_ERROR_ATTRIBUTE_BINDING_UNDEFINED.replace('%s', attributeName));
        }
    }

    this._updateUniformSetterMap();
};

Program.prototype._updateUniforms = function(){
    var gl = this._gl;
    var program     = this._handle;
    var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
    var uniforms    = this._uniforms = {};

    for(var i = 0, info, name; i < numUniforms; ++i){
        info = gl.getActiveUniform(program, i);
        name = info.name;
        uniforms[name] = {
            type : info.type,
            location : gl.getUniformLocation(program, name)
        };
    }
};

Program.prototype._updateAttributes = function(){
    var gl = this._gl;
    var program       = this._handle;
    var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
    var attributes    = this._attributes = {};

    for(var i = 0, info, name; i < numAttributes; ++i){
        info = gl.getActiveAttrib(program, i);
        name = info.name;
        attributes[name] = {
            type : info.type,
            location : gl.getAttribLocation(program, name)
        }
    }
};

Program.prototype._compileSource = function(type, src){
    var gl = this._gl;
    var shader = gl.createShader(type);

    gl.shaderSource(shader, src + '\n');
    gl.compileShader(shader);
    if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
        throw new Error((type === gl.VERTEX_SHADER ? 'Vertex ' : 'Fragment ') + 'shader: ' + gl.getShaderInfoLog(shader));
    }
    return shader;
};

Program.prototype._updateUniformSetterMap = function(){
    var gl = this._gl;

    this._uniformSetterMap = {};
    for(var entry in this._uniforms){
        var type = this._uniforms[entry].type;
        if(this._uniformSetterMap[type] === undefined){
            switch (type){
                case gl.INT:
                case gl.BOOL:
                case gl.SAMPLER_2D:
                case gl.SAMPLER_CUBE:
                    this._uniformSetterMap[gl.INT] = this._uniformSetterMap[gl.INT] || function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniform1i(location,x);
                    };
                    this._uniformSetterMap[type] = this._uniformSetterMap[gl.INT];
                    break;
                case gl.FLOAT:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniform1f(location,x);
                    };
                    break;
                case gl.FLOAT_VEC2:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || z !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform2fv(location,x);
                        }
                        else {
                            gl.uniform2f(location,x,y);
                        }
                    };
                    break;
                case gl.FLOAT_VEC3:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || w !== undefined || (y !== undefined && z === undefined)){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform3fv(location,x);
                        }
                        else {
                            gl.uniform3f(location,x,y,z);
                        }
                    };
                    break;
                case gl.FLOAT_VEC4:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || (y !== undefined && z === undefined) || (z !== undefined && w === undefined)){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform4fv(location,x);
                        }
                        else {
                            gl.uniform4f(location,x,y,z,w);
                        }
                    };
                    break;
                case gl.FLOAT_MAT2:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix2fv(location,false,x);
                    };
                    break;
                case gl.FLOAT_MAT3:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix3fv(location,false,x);
                    };
                    break;
                case gl.FLOAT_MAT4:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix4fv(location,false,x);
                    };
                    break;
                default:
                    throw new Error(STR_ERROR_INVALID_UNIFORM_TYPE.replace('%s',type));
                    break;
            }
        }
    }

};

Program.prototype.setUniform = function(name, x, y, z, w){
    var uniform = this._uniforms[name];
    if(uniform === undefined){
        throw new Error(STR_ERROR_UNIFORM_UNDEFINED.replace('%s', name));
    }
    this._uniformSetterMap[uniform.type](uniform.location,x,y,z,w);
};

Program.prototype.hasUniform = function(name){
    return this._uniforms[name] !== undefined;
};

Program.prototype.dispose = function(){
    if(!this._handle){
        return this;
    }
    this._gl.deleteProgram(this._handle);
    this._handle = null;
    return this;
};

module.exports = Program;
<commit_msg>Program moved default attrib locations name bindings to class<commit_after>var DEFAULT_ATTRIB_LOCATION_BINDING = {
    0 : 'aPosition',
    1 : 'aColor',
    2 : 'aTexCoord0',
    3 : 'aTexCoord1',
    4 : 'aTexCoord2',
    5 : 'aTexCoord3',
    6 : 'aNormal',
    7 : 'aTangent',
    8 : 'aBitangent',
    9 : 'aBoneIndex',
    10 : 'aBoneWeight',
    11 : 'aCustom0',
    12 : 'aCustom1',
    13 : 'aCustom2',
    14 : 'aCustom3',
    15 : 'aCustom4'
};

//TODO: this is true in 99% of cases, might be implementation specific
var NUM_VERTEX_ATTRIBUTES_MAX = 16;

var STR_ERROR_UNIFORM_UNDEFINED = 'Uniform "%s" is not defined.';
var STR_ERROR_WRONG_NUM_ARGS = 'Wrong number of arguments.';
var STR_ERROR_INVALID_UNIFORM_TYPE = 'Unsupported uniform type "%s".';
var STR_ERROR_ATTRIBUTE_BINDING_UNDEFINED = 'Attribute "%s" is not present in program.';

function Program(context, vertSrc, fragSrc, attributeLocationBinding){
    var gl = this._gl = context.getGL();

    this._handle           = gl.createProgram();
    this._attributes       = {};
    this._uniforms         = {};
    this._uniformSetterMap = {};
    if(vertSrc){
        this.update(vertSrc, fragSrc, attributeLocationBinding);
    }
}

Program.prototype.getHandle = function(){
    return this._handle;
};

Program.prototype._bindInternal = function(){
    this._gl.useProgram(this._handle);
};

/**
 * updates shaders sources and links the program
 * @param  {String} vertSrc                 - vert shader source (or combined vert/fragShader)
 * @param  {String} [fragSrc]               - frag shader source
 * @param  {String} [attributeLocationBinding] - attribute locations map { 0: 'aPositon', 1: 'aNormal', 2: 'aColor' }
 */
Program.prototype.update = function(vertSrc, fragSrc, attributeLocationBinding){
    var gl = this._gl;
    var program = this._handle;

    var vertShader = this._compileSource(gl.VERTEX_SHADER, vertSrc);
    var fragShader = this._compileSource(gl.FRAGMENT_SHADER, fragSrc);

    gl.attachShader(program, vertShader);
    gl.attachShader(program, fragShader);

    for(var location = 0; location < NUM_VERTEX_ATTRIBUTES_MAX; location++){
        var attributeName = (attributeLocationBinding && attributeLocationBinding[location]) || DEFAULT_ATTRIB_LOCATION_BINDING[location];
        gl.bindAttribLocation(program, location, attributeName);
    }

    gl.linkProgram(program);

    if(!gl.getProgramParameter(program, gl.LINK_STATUS)){
        throw new Error('PROGRAM: ' + gl.getProgramInfoLog(program));
    }

    //Mark for deletion, they are not actually deleted until you call deleteProgram() in dispose()
    gl.deleteShader(vertShader);
    gl.deleteShader(fragShader);

    this._updateUniforms();
    this._updateAttributes();

    for(var location in attributeLocationBinding){
        var attributeName = attributeLocationBinding[location];
        if(this._attributes[attributeName] === undefined){
            throw new Error(STR_ERROR_ATTRIBUTE_BINDING_UNDEFINED.replace('%s', attributeName));
        }
    }

    this._updateUniformSetterMap();
};

Program.prototype._updateUniforms = function(){
    var gl = this._gl;
    var program     = this._handle;
    var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
    var uniforms    = this._uniforms = {};

    for(var i = 0, info, name; i < numUniforms; ++i){
        info = gl.getActiveUniform(program, i);
        name = info.name;
        uniforms[name] = {
            type : info.type,
            location : gl.getUniformLocation(program, name)
        };
    }
};

Program.prototype._updateAttributes = function(){
    var gl = this._gl;
    var program       = this._handle;
    var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
    var attributes    = this._attributes = {};

    for(var i = 0, info, name; i < numAttributes; ++i){
        info = gl.getActiveAttrib(program, i);
        name = info.name;
        attributes[name] = {
            type : info.type,
            location : gl.getAttribLocation(program, name)
        }
    }
};

Program.prototype._compileSource = function(type, src){
    var gl = this._gl;
    var shader = gl.createShader(type);

    gl.shaderSource(shader, src + '\n');
    gl.compileShader(shader);
    if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
        throw new Error((type === gl.VERTEX_SHADER ? 'Vertex ' : 'Fragment ') + 'shader: ' + gl.getShaderInfoLog(shader));
    }
    return shader;
};

Program.prototype._updateUniformSetterMap = function(){
    var gl = this._gl;

    this._uniformSetterMap = {};
    for(var entry in this._uniforms){
        var type = this._uniforms[entry].type;
        if(this._uniformSetterMap[type] === undefined){
            switch (type){
                case gl.INT:
                case gl.BOOL:
                case gl.SAMPLER_2D:
                case gl.SAMPLER_CUBE:
                    this._uniformSetterMap[gl.INT] = this._uniformSetterMap[gl.INT] || function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniform1i(location,x);
                    };
                    this._uniformSetterMap[type] = this._uniformSetterMap[gl.INT];
                    break;
                case gl.FLOAT:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniform1f(location,x);
                    };
                    break;
                case gl.FLOAT_VEC2:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || z !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform2fv(location,x);
                        }
                        else {
                            gl.uniform2f(location,x,y);
                        }
                    };
                    break;
                case gl.FLOAT_VEC3:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || w !== undefined || (y !== undefined && z === undefined)){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform3fv(location,x);
                        }
                        else {
                            gl.uniform3f(location,x,y,z);
                        }
                    };
                    break;
                case gl.FLOAT_VEC4:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || (y !== undefined && z === undefined) || (z !== undefined && w === undefined)){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        if(y === undefined){
                            gl.uniform4fv(location,x);
                        }
                        else {
                            gl.uniform4f(location,x,y,z,w);
                        }
                    };
                    break;
                case gl.FLOAT_MAT2:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix2fv(location,false,x);
                    };
                    break;
                case gl.FLOAT_MAT3:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix3fv(location,false,x);
                    };
                    break;
                case gl.FLOAT_MAT4:
                    this._uniformSetterMap[type] = function(location,x,y,z,w){
                        if(x === undefined || y !== undefined){
                            throw new Error(STR_ERROR_WRONG_NUM_ARGS);
                        }
                        gl.uniformMatrix4fv(location,false,x);
                    };
                    break;
                default:
                    throw new Error(STR_ERROR_INVALID_UNIFORM_TYPE.replace('%s',type));
                    break;
            }
        }
    }

};

Program.prototype.setUniform = function(name, x, y, z, w){
    var uniform = this._uniforms[name];
    if(uniform === undefined){
        throw new Error(STR_ERROR_UNIFORM_UNDEFINED.replace('%s', name));
    }
    this._uniformSetterMap[uniform.type](uniform.location,x,y,z,w);
};

Program.prototype.hasUniform = function(name){
    return this._uniforms[name] !== undefined;
};

Program.prototype.dispose = function(){
    if(!this._handle){
        return this;
    }
    this._gl.deleteProgram(this._handle);
    this._handle = null;
    return this;
};

module.exports = Program;
<|endoftext|>


<commit_before>var Class = require('./Class'),
  bind = require('./bind'),
  invokeWith = require('./invokeWith')

module.exports = Class(function() {
  this.init = function() {
    this.dependants_ = []
    this.fulfillment_ = null
  }

  this.add = function(callback) {
    if (!callback || !callback.apply) debugger
    if (this.fulfillment_) { callback.apply(this, this.fulfillment_) }
    else { this.dependants_.push(callback) }
  }

  this.fulfill = function(/* arg1, arg2, ...*/) {
    if (this.fulfillment_) { throw new Error('Promise fulfilled twice') }
    this.fulfillment_ = slice(arguments)
    each(this.dependants_, invokeWith(this.fulfillment_))
  }
})
<commit_msg>bug fix - the fulfillment arguments were being delivered as an array as opposed to a variable number of argument for delayed dependants<commit_after>var Class = require('./Class'),
  bind = require('./bind'),
  invokeWith = require('./invokeWith')

module.exports = Class(function() {
  this.init = function() {
    this.dependants_ = []
    this.fulfillment_ = null
  }

  this.add = function(callback) {
    if (!callback || !callback.apply) debugger
    if (this.fulfillment_) { callback.apply(this, this.fulfillment_) }
    else { this.dependants_.push(callback) }
  }

  this.fulfill = function(/* arg1, arg2, ...*/) {
    if (this.fulfillment_) { throw new Error('Promise fulfilled twice') }
    this.fulfillment_ = slice(arguments)
    each(this.dependants_, invokeWith.apply(this, this.fulfillment_))
  }
})
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from "react";
import {Link} from "react-router";
import {
	LIST_PATH,
	ACCOUNT_PATH,
	LOGIN_PATH,
	SIGNUP_PATH
} from "constants/paths";

// Components
import AppBar from "material-ui/AppBar";
import IconMenu from "material-ui/IconMenu";
import IconButton from "material-ui/IconButton";
import MenuItem from "material-ui/MenuItem";
import FlatButton from "material-ui/FlatButton";
import Avatar from "material-ui/Avatar";
import StockPhoto from "static/User.png";

const originSettings = {horizontal: "right", vertical: "top"};
const buttonStyle = {color: "white", textDecoration: "none"};
const avatarSize = 50;

const avatarStyles = {
	icon: {width: avatarSize, height: avatarSize},
	button: {marginRight: "1.5rem", width: avatarSize, height: avatarSize},
	wrapper: {marginTop: 45 - avatarSize}
};

import {connect} from "react-redux";
import {firebase, helpers} from "react-redux-firebase";
const {pathToJS} = helpers;

// Props decorators
@firebase()
@connect(({firebase})=>({
	authError: pathToJS(firebase, "authError"),
	auth: pathToJS(firebase, "auth"),
	account: pathToJS(firebase, "profile")
}))
export default class Navbar extends Component {
	static contextTypes = {
		router: PropTypes.object.isRequired
	};
	static propTypes = {
		auth: PropTypes.object,
		firebase: PropTypes.object.isRequired
	};

	handleLogout() {
		this.props.firebase.logout();
		this.context.router.push("/");
	}

	/*render() {
		const {auth} = this.props;

		const iconButton = (
			<IconButton iconStyle={avatarStyles.icon} style={avatarStyles.button}>
				<Avatar src={auth && auth.photoURL ? auth.photoURL : StockPhoto}/>
			</IconButton>
		);

		const mainMenu = (

				<Link to={SIGNUP_PATH}>
					<FlatButton label="Sign Up" style={buttonStyle}/>
				</Link>
				<Link to={LOGIN_PATH}>
					<FlatButton label="Login" style={buttonStyle}/>
				</Link>

		);

		const rightMenu = auth ? (
			<IconMenu iconButtonElement={iconButton}
					targetOrigin={{horizontal: "right", vertical: "bottom"}}
					anchorOrigin={originSettings} animated={false}>
				<MenuItem primaryText="Account" value="account"
					onTouchTap={()=> this.context.router.push(ACCOUNT_PATH)}/>
				<MenuItem primaryText="Sign out" value="logout" onTouchTap={this.handleLogout}/>
			</IconMenu>
		) : mainMenu;

		// Only apply styling if avatar is showing
		const menuStyle = auth ? avatarStyles.wrapper : {};

		// Redirect to projects page if logged in
		const brandPath = auth ? `/${LIST_PATH}` : "/";

		return (
			<AppBar
				title={
					<Link to={brandPath}>
						Thesis Map
					</Link>
				}
				showMenuIconButton={false}
				iconElementRight={rightMenu}
				iconStyleRight={menuStyle}
			/>
		);
	}*/

	render() {
		var {store} = this.context;
		var {page} = store || {};
		return (

				{
							// todo: navigate to home
						}}>
					Thesis Map

				<NavBarButton page="" text="Home" active={page == ""}/>
				<NavBarButton page="community" text="Community" active={page == "community"}/>
				<NavBarButton page="definitions" text="Definitions" active={page == "definitions"}/>
				<NavBarButton page="global-map" text="Global Map" active={page == "global-map"}/>
				<NavBarButton page="discussion-maps" text="Discussion Maps" active={page == "discussion-maps"}/>
				<NavBarButton page="personal-maps" text="Personal Maps" active={page == "personal-maps"}/>

{}}/>

{}}/>

		);
	}
}

class NavBarButton extends Component {
	render() {
		var {page, text, active} = this.props;
		return (
			 {
						// todo: navigate to page
					}}>
				{text}

		);
	}
}<commit_msg>* Added forum button.<commit_after>import React, {Component, PropTypes} from "react";
import {Link} from "react-router";
import {
	LIST_PATH,
	ACCOUNT_PATH,
	LOGIN_PATH,
	SIGNUP_PATH
} from "constants/paths";

// Components
import AppBar from "material-ui/AppBar";
import IconMenu from "material-ui/IconMenu";
import IconButton from "material-ui/IconButton";
import MenuItem from "material-ui/MenuItem";
import FlatButton from "material-ui/FlatButton";
import Avatar from "material-ui/Avatar";
import StockPhoto from "static/User.png";

const originSettings = {horizontal: "right", vertical: "top"};
const buttonStyle = {color: "white", textDecoration: "none"};
const avatarSize = 50;

const avatarStyles = {
	icon: {width: avatarSize, height: avatarSize},
	button: {marginRight: "1.5rem", width: avatarSize, height: avatarSize},
	wrapper: {marginTop: 45 - avatarSize}
};

import {connect} from "react-redux";
import {firebase, helpers} from "react-redux-firebase";
const {pathToJS} = helpers;

// Props decorators
@firebase()
@connect(({firebase})=>({
	authError: pathToJS(firebase, "authError"),
	auth: pathToJS(firebase, "auth"),
	account: pathToJS(firebase, "profile")
}))
export default class Navbar extends Component {
	static contextTypes = {
		router: PropTypes.object.isRequired
	};
	static propTypes = {
		auth: PropTypes.object,
		firebase: PropTypes.object.isRequired
	};

	handleLogout() {
		this.props.firebase.logout();
		this.context.router.push("/");
	}

	/*render() {
		const {auth} = this.props;

		const iconButton = (
			<IconButton iconStyle={avatarStyles.icon} style={avatarStyles.button}>
				<Avatar src={auth && auth.photoURL ? auth.photoURL : StockPhoto}/>
			</IconButton>
		);

		const mainMenu = (

				<Link to={SIGNUP_PATH}>
					<FlatButton label="Sign Up" style={buttonStyle}/>
				</Link>
				<Link to={LOGIN_PATH}>
					<FlatButton label="Login" style={buttonStyle}/>
				</Link>

		);

		const rightMenu = auth ? (
			<IconMenu iconButtonElement={iconButton}
					targetOrigin={{horizontal: "right", vertical: "bottom"}}
					anchorOrigin={originSettings} animated={false}>
				<MenuItem primaryText="Account" value="account"
					onTouchTap={()=> this.context.router.push(ACCOUNT_PATH)}/>
				<MenuItem primaryText="Sign out" value="logout" onTouchTap={this.handleLogout}/>
			</IconMenu>
		) : mainMenu;

		// Only apply styling if avatar is showing
		const menuStyle = auth ? avatarStyles.wrapper : {};

		// Redirect to projects page if logged in
		const brandPath = auth ? `/${LIST_PATH}` : "/";

		return (
			<AppBar
				title={
					<Link to={brandPath}>
						Thesis Map
					</Link>
				}
				showMenuIconButton={false}
				iconElementRight={rightMenu}
				iconStyleRight={menuStyle}
			/>
		);
	}*/

	render() {
		var {store} = this.context;
		var {page} = store || {};
		return (

				{
							// todo: navigate to home
						}}>
					Thesis Map

				<NavBarButton page="" text="Home" active={page == ""}/>
				<NavBarButton page="community" text="Community" active={page == "community"}/>
				<NavBarButton page="forum" text="Forum" active={page == "forum"}/>
				<NavBarButton page="definitions" text="Definitions" active={page == "definitions"}/>
				<NavBarButton page="global-map" text="Global Map" active={page == "global-map"}/>
				<NavBarButton page="discussion-maps" text="Discussion Maps" active={page == "discussion-maps"}/>
				<NavBarButton page="personal-maps" text="Personal Maps" active={page == "personal-maps"}/>

{}}/>

{}}/>

		);
	}
}

class NavBarButton extends Component {
	render() {
		var {page, text, active} = this.props;
		return (
			 {
						// todo: navigate to page
					}}>
				{text}

		);
	}
}<|endoftext|>


<commit_before>import React, { Component } from 'react';
// react-md
import {
  TextField,
  Button,
  Collapse,
} from 'react-md';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import Loading from '../components/Loading'
import { RedirectToken } from '../components/RedirectToken'

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {
      st: '',
      collapsed: false,
      submitted: false,
      open: false,
      jobId: "",
      hasResult: false,
    }
  }
  toggle = () => {
    this.setState({ collapsed: !this.state.collapsed });
  };
  _updateSt = (value) => {
    this.setState({ st: value });
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // Create form.
    var data = new FormData()
    data.append('st', this.state.st)
    // POST
    axios.post(API_ROOT + 'search', data)
      .then(response => {
        console.log("RESPONSE")
        console.log(response)
        let jobId = response.data
        this.setState({ jobId })
        // Handle the return.
        this.props.dispatch(addJob(jobId,
          'search',
          new Date().toLocaleString(),
          String('Search for ' + this.state.st + ' at: ' + new Date().toLocaleString())
        ))
        this.setState({ hasResult: true })
      })
  };
  render(){
    const { st, hasResult, collapsed } = this.state;
    const { token } = this.props;
    return (

        <RedirectToken token={token} />
        {/* actual form */}
        {(!hasResult)?
          <form className="md-text-container md-grid">

              {/* Help Text */}
              <Button hidden raised primary swapTheming label='Help' onClick={this.toggle}>
                help_outline
              </Button>
              <Collapse collapsed={collapsed}>

Description:

                    We use the SeqIO
                    library to parse the accession numbers from an isolate.
                    Specifically, we use the record.id

                    For example, a genbank record:

                    Escherichia coli strain 97-3250 chromosome, complete genome

                    5,942,969 bp circular DNA

                    CP027599.1 GI:1370526529

                    With fasta header:

                    >gi|1370526529|gb|CP027599.1| Escherichia coli strain 97-3250 chromosome, complete genome

                    Has accession CP027599.1

              </Collapse>

            {/* End: Help Text */}

Search By Accession

              <TextField
                id="st"
                value={st}
                onChange={this._updateSt}
                helpText="Accession #"
              />

              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                onClick={this._handleSubmit}
              />

          </form> :
          <Loading jobId={this.state.jobId} />
        }

    )
  }
}

Search = connect()(Search)

export default Search
<commit_msg>edit: record.id was diff than i expected<commit_after>import React, { Component } from 'react';
// react-md
import {
  TextField,
  Button,
  Collapse,
} from 'react-md';
// redux
import { connect } from 'react-redux'
import { addJob } from '../actions'
// axios
import axios from 'axios'
import { API_ROOT } from '../middleware/api'
// router
import Loading from '../components/Loading'
import { RedirectToken } from '../components/RedirectToken'

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {
      st: '',
      collapsed: false,
      submitted: false,
      open: false,
      jobId: "",
      hasResult: false,
    }
  }
  toggle = () => {
    this.setState({ collapsed: !this.state.collapsed });
  };
  _updateSt = (value) => {
    this.setState({ st: value });
  }
  _handleSubmit = (e) => {
    e.preventDefault() // disable default HTML form behavior
    // Create form.
    var data = new FormData()
    data.append('st', this.state.st)
    // POST
    axios.post(API_ROOT + 'search', data)
      .then(response => {
        console.log("RESPONSE")
        console.log(response)
        let jobId = response.data
        this.setState({ jobId })
        // Handle the return.
        this.props.dispatch(addJob(jobId,
          'search',
          new Date().toLocaleString(),
          String('Search for ' + this.state.st + ' at: ' + new Date().toLocaleString())
        ))
        this.setState({ hasResult: true })
      })
  };
  render(){
    const { st, hasResult, collapsed } = this.state;
    const { token } = this.props;
    return (

        <RedirectToken token={token} />
        {/* actual form */}
        {(!hasResult)?
          <form className="md-text-container md-grid">

              {/* Help Text */}
              <Button hidden raised primary swapTheming label='Help' onClick={this.toggle}>
                help_outline
              </Button>
              <Collapse collapsed={collapsed}>

Description:

                    We use the SeqIO
                    library to parse the identifiers from an isolate.
                    Specifically, we use the record.id which uses the combined
                    gi gb accession numbers.

                    For example, a genbank record:

                    Escherichia coli strain 97-3250 chromosome, complete genome

                    5,942,969 bp circular DNA

                    CP027599.1 GI:1370526529

                    With fasta header:

                    >gi|1370526529|gb|CP027599.1| Escherichia coli strain 97-3250 chromosome, complete genome

                    Would have a record.id of gi|1370526529|gb|CP027599.1|

              </Collapse>

            {/* End: Help Text */}

Search By record.id

              <TextField
                id="st"
                value={st}
                onChange={this._updateSt}
                helpText="gi|1370526529|gb|CP027599.1|"
              />

              <Button
                raised
                secondary
                type="submit"
                label="Submit"
                onClick={this._handleSubmit}
              />

          </form> :
          <Loading jobId={this.state.jobId} />
        }

    )
  }
}

Search = connect()(Search)

export default Search
<|endoftext|>


<commit_before>import mongoose from 'mongoose';
import Promise from 'bluebird';

import { createCommand } from '../sockets';
import { GenericError } from '../errors';

const ObjectId = mongoose.Types.ObjectId;

export const getBooth = function getBooth(uwave) {
  const History = uwave.mongo.model('History');

  const booth = {
    'historyID': null,
    'playlistID': null,
    'played': 0,
    'userID': null,
    'media': null,
    'stats': {
      'upvotes': 0,
      'downvotes': 0,
      'favorite': 0
    }
  };

  return uwave.redis.get('booth:historyID')
  .then(historyID => {
    booth.historyID = historyID;
    return History.findOne(ObjectId(historyID)).populate('media');
  })
  .then(entry => {
    if (entry) {
      booth.userID = entry.user.toString();
      booth.playlistID = entry.playlist.toString();
      booth.played = entry.played;
      booth.media = entry.media;
    }

    return uwave.redis.llen('booth:upvotes');
  })
  .then(upvotes => {
    booth.stats.upvotes = upvotes;
    return uwave.redis.llen('booth:downvotes');
  })
  .then(downvotes => {
    booth.stats.downvotes = downvotes;
    return uwave.redis.llen('booth:favorite');
  })
  .then(favorite => {
    booth.stats.favorite = favorite;
    return booth;
  });
};

export const skipBooth = function skipBooth(moderatorID, id, reason, uwave) {
  uwave.redis.publish('v1', createCommand('skip', {
    'moderatorID': moderatorID,
    'userID': id,
    'reason': reason
  }));
  uwave.redis.publish('v1p', createCommand('advance', null));
};

export const replaceBooth = function replaceBooth(moderatorID, id, uwave) {
  let next = null;

  uwave.redis.lrange('waitlist')
  .then(waitlist => {
    if (!waitlist.length) throw new GenericError(404, 'waitlist is empty');

    for (let i = waitlist.length - 1; i >= 0; i--) {
      if (waitlist[i] === id) {
        uwave.redis.lrem('waitlist', 1, id);
        return uwave.redis.lpush('waitlist', id);
      }
    }
  })
  .then(waitlist => {
    uwave.redis.publish('v1', createCommand('boothReplace', {
      'moderatorID': moderatorID,
      'userID': id
    }));
    uwave.redis.publish('v1p', createCommand('advance', null));
    return waitlist;
  });
};

export const favorite = function favorite(id, playlistID, historyID, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  const History = uwave.mongo.model('History');
  const User = uwave.mongo.model('User');

  let _mediaID;

  return History.findOne(ObjectId(historyID))
  .then(history => {
    if (!history) throw new GenericError(404, `history entry with ID ${historyID} not found`);
    if (history.user.toString() === id) throw new GenericError(403, 'you can\'t grab your own song');

    _mediaID = history.media.toString();
    return Playlist.findOne(ObjectId(playlistID));
  })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `Playlist with ID ${playlistID} not found`);
    if (playlist.author !== id) {
      throw new GenericError(403, 'you are not allowed to edit playlists of other users');
    }

    playlist.media.push(_mediaID);

    this.redis.lrem('booth:favorite', 0, id);
    this.redis.lpush('booth:favorite', id);
    uwave.redis.publish('v1', createCommand('favorite', {
      'userID': id,
      'playlistID': playlistID
    }));
    return playlist.save();
  });
};
<commit_msg>populate media.media; resolves #29<commit_after>import mongoose from 'mongoose';
import Promise from 'bluebird';

import { createCommand } from '../sockets';
import { GenericError } from '../errors';

const ObjectId = mongoose.Types.ObjectId;

export const getBooth = function getBooth(uwave) {
  const History = uwave.mongo.model('History');

  const booth = {
    'historyID': null,
    'playlistID': null,
    'played': 0,
    'userID': null,
    'media': null,
    'stats': {
      'upvotes': 0,
      'downvotes': 0,
      'favorite': 0
    }
  };

  return uwave.redis.get('booth:historyID')
  .then(historyID => {
    booth.historyID = historyID;
    return History.findOne(ObjectId(historyID)).populate('media')
    .then(entry => {
      if (!entry) throw new GenericError(404, 'booth is empty');

      return History.populate(entry, { 'path': 'media.media', 'model': 'Media' });
    });
  })
  .then(entry => {
    if (entry) {
      booth.userID = entry.user.toString();
      booth.playlistID = entry.playlist.toString();
      booth.played = entry.played;
      booth.media = entry.media;
    }

    return uwave.redis.llen('booth:upvotes');
  })
  .then(upvotes => {
    booth.stats.upvotes = upvotes;
    return uwave.redis.llen('booth:downvotes');
  })
  .then(downvotes => {
    booth.stats.downvotes = downvotes;
    return uwave.redis.llen('booth:favorite');
  })
  .then(favorite => {
    booth.stats.favorite = favorite;
    return booth;
  });
};

export const skipBooth = function skipBooth(moderatorID, id, reason, uwave) {
  uwave.redis.publish('v1', createCommand('skip', {
    'moderatorID': moderatorID,
    'userID': id,
    'reason': reason
  }));
  uwave.redis.publish('v1p', createCommand('advance', null));
};

export const replaceBooth = function replaceBooth(moderatorID, id, uwave) {
  let next = null;

  uwave.redis.lrange('waitlist')
  .then(waitlist => {
    if (!waitlist.length) throw new GenericError(404, 'waitlist is empty');

    for (let i = waitlist.length - 1; i >= 0; i--) {
      if (waitlist[i] === id) {
        uwave.redis.lrem('waitlist', 1, id);
        return uwave.redis.lpush('waitlist', id);
      }
    }
  })
  .then(waitlist => {
    uwave.redis.publish('v1', createCommand('boothReplace', {
      'moderatorID': moderatorID,
      'userID': id
    }));
    uwave.redis.publish('v1p', createCommand('advance', null));
    return waitlist;
  });
};

export const favorite = function favorite(id, playlistID, historyID, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  const History = uwave.mongo.model('History');
  const User = uwave.mongo.model('User');

  let _mediaID;

  return History.findOne(ObjectId(historyID))
  .then(history => {
    if (!history) throw new GenericError(404, `history entry with ID ${historyID} not found`);
    if (history.user.toString() === id) throw new GenericError(403, 'you can\'t grab your own song');

    _mediaID = history.media.toString();
    return Playlist.findOne(ObjectId(playlistID));
  })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, `Playlist with ID ${playlistID} not found`);
    if (playlist.author !== id) {
      throw new GenericError(403, 'you are not allowed to edit playlists of other users');
    }

    playlist.media.push(_mediaID);

    this.redis.lrem('booth:favorite', 0, id);
    this.redis.lpush('booth:favorite', id);
    uwave.redis.publish('v1', createCommand('favorite', {
      'userID': id,
      'playlistID': playlistID
    }));
    return playlist.save();
  });
};
<|endoftext|>


<commit_before>import {REVISION} from 'three';
import Events from 'minivents';
import {ManagerError} from './errors';

// Check for Three.js
const warnDeps = () => {
  throw new Error('WhitestormJS Framework requires Three.js r84. https://threejs.org/');
};

try {
  if (!REVISION) warnDeps();
} catch (err) {
  warnDeps();
}

export class ModuleSystem extends Events {
  // INTEGRATING

  integrateModules(source) {
    if (source) this.modules = source.modules.slice(0);

    for (let i = 0, max = this.modules.length; i < max; i++)
      this.applyModule(this.modules[i], false);

    if (source) this.applyBridge({onCopy: source});
  }

  // APPLYING MODULE (...and a "bridge" for module)

  applyBridge(bridgeMap = {}) {
    const modules = this.modules;

    for (let i = 0, max = modules.length; i < max; i++) {
      for (const key in bridgeMap) {
        if (bridgeMap[key]) {
          const module = modules[i];

          if (module && module.bridge && module.bridge[key])
            bridgeMap[key] = module.bridge[key].apply(this, [bridgeMap[key], module]);
        }
      }
    }

    return bridgeMap;
  }

  applyModule(module, push = true) {
    if (!module) return;
    if (push) this.modules.push(module);

    if (this.manager) this.manager.active(module);

    if (module.manager && this.manager) module.manager(this.manager);
    else if (module.manager) {
      throw new ManagerError(
        'Component',
        `Module requires ModuleManager that is turned off for this component`,
        this, module
      );
    }

    if (module.integrate) module.integrate.bind(this)(module);

    return module;
  }

  applyModuleOnce(ModuleConstructor, getModule, push = true) {
    const isAlreadyIncluded = this.modules.some(m => m instanceof ModuleConstructor);
    if (!isAlreadyIncluded) return this.applyModule(getModule(), push);
  }

  disposeModules() {
    while (this.modules.length)
      this.disposeModule(this.modules[0]);
  }

  disposeModule(module) {
    if (!module) return;

    this.modules.splice(this.modules.indexOf(module), 1);

    if (module.dispose) module.dispose.bind(this)(module);

    return module;
  }

  // PIPED METHOD

  module(module) {
    this.applyModule(module);
    return this;
  }
}
<commit_msg>Adds doc for ModuleSystem - #189<commit_after>import {REVISION} from 'three';
import Events from 'minivents';
import {ManagerError} from './errors';

// Check for Three.js
const warnDeps = () => {
  throw new Error('WhitestormJS Framework requires Three.js r84. https://threejs.org/');
};

try {
  if (!REVISION) warnDeps();
} catch (err) {
  warnDeps();
}

/**
 * @class ModuleSystem
 * @description  Provides API for classes that will use Modules.

 * This class includes basic event system with those supported methods:
 *
.on()

.off()

.emit()

 * @extends Events
 * @memberof module:core
 */
export class ModuleSystem extends Events {
  // INTEGRATING

  /**
   * @method integrateModules
   * @description This method applies all modules from .modules collection.
   * @param {Object} [source] If source (should be a component) is provided, will replace .modules with source's one before executing modules.
   * @memberof module:core.ModuleSystem
   */
  integrateModules(source) {
    if (source) this.modules = source.modules.slice(0);

    for (let i = 0, max = this.modules.length; i < max; i++)
      this.applyModule(this.modules[i], false);

    if (source) this.applyBridge({onCopy: source});
  }

  // APPLYING MODULE (...and a "bridge" for module)

  /**
   * @method applyBridge
   * @description Makes component-specific API to work with modules.
   * @param {Object} bridgeMap
   * @return {Object} Returns object with modified values.
   * @memberof module:core.ModuleSystem
   */
  applyBridge(bridgeMap = {}) {
    const modules = this.modules;

    for (let i = 0, max = modules.length; i < max; i++) {
      for (const key in bridgeMap) {
        if (bridgeMap[key]) {
          const module = modules[i];

          if (module && module.bridge && module.bridge[key])
            bridgeMap[key] = module.bridge[key].apply(this, [bridgeMap[key], module]);
        }
      }
    }

    return bridgeMap;
  }

  /**
   * @method applyModule
   * @description .applyModule is also used in .integrateModules() function.
   * It does exactly what its name says (applies module to component or app).
   * @param {Object} module the module to apply
   * @param {Boolean} [push=true]
   * @return {Object} Returns module that was applied.
   * @throws {ManagerError}
   * @memberof module:core.ModuleSystem
   */
  applyModule(module, push = true) {
    if (!module) return;
    if (push) this.modules.push(module);

    if (this.manager) this.manager.active(module);

    if (module.manager && this.manager) module.manager(this.manager);
    else if (module.manager) {
      throw new ManagerError(
        'Component',
        `Module requires ModuleManager that is turned off for this component`,
        this, module
      );
    }

    if (module.integrate) module.integrate.bind(this)(module);

    return module;
  }

  applyModuleOnce(ModuleConstructor, getModule, push = true) {
    const isAlreadyIncluded = this.modules.some(m => m instanceof ModuleConstructor);
    if (!isAlreadyIncluded) return this.applyModule(getModule(), push);
  }

  disposeModules() {
    while (this.modules.length)
      this.disposeModule(this.modules[0]);
  }

  disposeModule(module) {
    if (!module) return;

    this.modules.splice(this.modules.indexOf(module), 1);

    if (module.dispose) module.dispose.bind(this)(module);

    return module;
  }

  // PIPED METHOD

  /**
   * @method module
   * @description piped version of .applyModule().
   * @param {Object} module the module to apply
   * @return {Object} returns this - app/component
   * @throws {ManagerError}
   * @memberof module:core.ModuleSystem
   * @example
Piped modules

   * component
   *   .module(new Module1())
   *   .module(new Module2())
   *   .module(new Module3())
   */
  module(module) {
    this.applyModule(module);
    return this;
  }
}
<|endoftext|>


<commit_before>/*
**  BindingJS -- View Data Binding for JavaScript <http://bindingjs.com>
**  Copyright (c) 2014 Johannes Rummel
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License (MPL), version 2.0. If a copy of the MPL was not distributed
**  with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

$api.plugin("attr", ($api, _api) => {
    return {
        getPaths: (element, path) => {
            return [path]
        },

        getValue: (element, path) => {
            if (path.length !== 1) {
                throw _api.util.exception("attr requires a Qualifier")
            }
            return element.attr(path[0])
        },

        set: (element, path, value) => {
            if (path.length !== 1) {
                throw _api.util.exception("attr requires a Qualifier")
            }

            let name = path[0]
            switch (name) {
                case "checked":
                    element.prop("checked", name ? true : false)
                    break
                default:
                    element.attr(name, value)
                    break
            }
        },

        type: () => {
            return "view"
        }
    }
})
<commit_msg>Bugfix in attr Adapter<commit_after>/*
**  BindingJS -- View Data Binding for JavaScript <http://bindingjs.com>
**  Copyright (c) 2014 Johannes Rummel
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License (MPL), version 2.0. If a copy of the MPL was not distributed
**  with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

$api.plugin("attr", ($api, _api) => {
    return {
        getPaths: (element, path) => {
            return [path]
        },

        getValue: (element, path) => {
            if (path.length !== 1) {
                throw _api.util.exception("attr requires a Qualifier")
            }
            return element.attr(path[0])
        },

        set: (element, path, value) => {
            if (path.length !== 1) {
                throw _api.util.exception("attr requires a Qualifier")
            }

            let name = path[0]
            switch (name) {
                case "checked":
                    element.prop("checked", value ? true : false)
                    break
                default:
                    element.attr(name, value)
                    break
            }
        },

        type: () => {
            return "view"
        }
    }
})
<|endoftext|>


<commit_before>/**
 * Device controller that produces test devices.
 *
 * Device controller that produces test devices and simulates device
 * interactions.
 *
 * @author A. Samuel Pottinger (LabJack, 2013)
**/

var async = require('async');
var dict = require('dict');
var q = require('q');
var labjack_nodejs = require('labjack-nodejs');
var labjack_driver = new labjack_nodejs.driver();

var LJM_DT_T7 = labjack_nodejs.driver_const.LJM_DT_T7.toString();
var DEVICE_TYPE_NAMES = dict({
    '7': 'T7'
});

var CONNECT_TYPE_USB = 1;
var CONNECTION_TYPE_NAMES = dict({
    '1': 'USB',
    '3': 'Ethernet',
    '4': 'Wifi'
});

/**
 * Object with information about a device.
 *
 * @param {String} serial The serial number for the device.
 * @param {String} connectionType The type of connection used to communicate
 *      with the device. Examples include "USB", "Ethernet", and "WiFi".
 * @param {String} deviceType The type of model this device is. Examples include
 *      T7 and Digit-TL.
**/
var Device = function (device, serial, connectionType, deviceType)
{
    this.device = device;
    this.cachedName = null;

    /**
     * Get the serial number for this device.
     *
     * @return {String} The serial number for this device.
    **/
    this.getSerial = function () {
        return serial;
    };

    /**
     * Get the type of connection being used to communicate with this device.
     *
     * Get the type of connection being used to communicate with this device.
     * Examples include "USB", "Ethernet", and "WiFi".
     *
     * @return {String} The type of connection being used to communicate with
     *      this device.
    **/
    this.getConnectionType = function () {
        return connectionType;
    };

    /**
     * Get the type of model this device is.
     *
     * Get a String describing what kind of device this is. Examples include
     * "T7" and "Digit-TL".
     *
     * @return {String} A description of the type of device this is.
    **/
    this.getDeviceType = function () {
        return DEVICE_TYPE_NAMES.get(String(deviceType), 'Other');
    };

    /**
     * Get the user-assigned name for this device.
     *
     * Get the name of this device as assigned by a previous authorized user
     * (name not set by default).
     *
     * @return {String} The name of this device.
    **/
    this.getName = function () {
        if (this.cachedName === null)
            this.cachedName = this.device.readSync('DEVICE_NAME_DEFAULT');
        return this.cachedName;
    };

    // TODO
    this.getFirmwareVersion = function () {
        return this.device.readSync('FIRMWARE_VERSION');
    };

    // TODO
    this.getBootloaderVersion = function () {
        return this.device.readSync('BOOTLOADER_VERSION');
    };

    this.writeMany = function (addresses, values) {
        var deferred = q.defer();

        console.log(addresses, values);
        this.device.writeMany(
            addresses,
            values,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.readMany = function (addresses) {
        var deferred = q.defer();

        this.device.readMany(
            addresses,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.writeAsync = function(address, value) {
        var deferred = q.defer();

        this.device.write(
            address,
            value,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.write = function (address, value) {
        this.device.writeSync(address, value);
    };

    this.read = function (address) {
        return this.device.readSync(address);
    };

    this.close = function (onError, onSuccess) {
        this.device.close(onError, onSuccess);
    };

    this.setName = function (newName) {
        this.write('DEVICE_NAME_DEFAULT', newName);
        this.cachedName = newName;
    };
};

// TODO: Cannot rely on serial number alone.
// TODO: This should be in a seperate module.
/**
 * A record keeper that holds a list of devices.
 *
 * A record keeper that holds a list of devices. Example usages include holding
 * a list of devices that are currently open.
**/
function DeviceKeeper()
{
    var devices = dict();

    /**
     * Add a new device to this keeper.
     *
     * @param {Device} device The device to add to this keeper.
    **/
    this.addDevice = function(device)
    {
        devices.set(device.getSerial(), device);
    };

    /**
     * Deermine how many devices this keeper has in it.
     *
     * @return {Number} The number of devices this keeper currently has in it.
    **/
    this.getNumDevices = function()
    {
        return devices.size;
    };

    /**
     * Remove a device from this keeper.
     *
     * @param {Device} device The device or equivalent device to remove from
     *      this keeper. The device removed from the keeper will be the one with
     *      the same serial number.
    **/
    this.removeDevice = function(device)
    {
        if(devices.has(device.getSerial()))
            devices.delete(device.getSerial());
    };

    /**
     * Get a device from this keeper.
     *
     * Get a device from this keeper based on a serial number. Will return null
     * if the device is not in this keeper.
     *
     * @return {Device} The device with the given serial number of null if no
     *      device by that serial number is in this keeper.
    **/
    this.getDevice = function(serial)
    {
        if(devices.has(serial))
            return devices.get(serial);
        else
            return null;
    };

    this.getDevices = function()
    {
        var retList = [];
        devices.forEach(function(value, key) {retList.push(value);});
        return retList;
    };

    this.getDeviceSerials = function()
    {
        var retList = [];
        devices.forEach(function(value, key) {retList.push(key);});
        return retList;
    };

    this.updateDevice = function (device) {
        this.removeDevice(device);
        this.addDevice(device);
    };
}

var deviceKeeperInstance = null;

function openDeviceFromAttributes (deviceType, serialNumber, ipAddress,
    connectionType, onError, onSuccess)
{
    var device;
    if (connectionType == CONNECT_TYPE_USB) {
        device = new labjack_nodejs.device();
        device.open(
            deviceType,
            connectionType,
            String(serialNumber),
            onError,
            function () { onSuccess(device); }
        );
    } else {
        device = new labjack_nodejs.device();
        device.open(
            deviceType,
            connectionType,
            ipAddress,
            onError,
            function () { onSuccess(device); }
        );
    }
}

/**
 * Get the device keeper singlton instance maintaining the list of open devices.
 *
 * @return {DeviceKeeper} The device keeper used system wide that maintains a
 *      list of all open devices.
**/
exports.getDeviceKeeper = function()
{
    if(deviceKeeperInstance === null)
        deviceKeeperInstance = new DeviceKeeper();
    return deviceKeeperInstance;
};

function markConnectedDevices(devices, onSuccess, onError)
{
    var devicesOfType;
    var device;

    var connectedSerials = exports.getDeviceKeeper().getDeviceSerials();

    var devicesLen = devices.length;
    var connectedDevices = [];
    for(var i=0; i<devicesLen; i++)
    {
        devicesOfType = devices[i].devices;
        var devicesOfTypeLen = devicesOfType.length;
        for(var j=0; j<devicesOfTypeLen; j++)
        {
            device = devicesOfType[j];
            if (connectedSerials.indexOf(device.serial.toString()) != -1)
                connectedDevices.push(device);
            else
                device.connected = false;
        }
    }

    async.each(
        connectedDevices,
        function (item, callback) {
            openDeviceFromAttributes(
                device.origDeviceType,
                device.serial,
                device.ipAddress,
                device.origConnectionType,
                function (err) {
                    console.log('===err===');
                    console.log(err);
                    device.connected = false;
                    callback();
                },
                function (newInner) {
                    var convConnType = device.origConnectionType;
                    var newDecoratedDevice = new Device(
                        newInner,
                        String(device.serial),
                        convConnType,
                        device.origDeviceType
                    );
                    exports.getDeviceKeeper().updateDevice(newDecoratedDevice);
                    device.connected = true;
                    callback();
                }
            );
        },
        function (err) {
            onSuccess(devices);
        }
    );
}

function getListingEntry (listingDict, device)
{
    var deviceType = String(device.deviceType);

    if (!listingDict.has(deviceType)) {
        listingDict.set(
            deviceType,
            {
                'name': DEVICE_TYPE_NAMES.get(deviceType, 'other'),
                'devices': []
            }
        );
    }

    return listingDict.get(deviceType);
}

function createDeviceListingRecord (device, name, specText, specImageSuffix)
{
    var connectionType = CONNECTION_TYPE_NAMES.get(
        String(device.connectionType), 'other');
    var deviceType = DEVICE_TYPE_NAMES.get(String(device.deviceType), 'other');

    return {
        'serial': device.serialNumber,
        'connectionTypes': [connectionType],
        'origConnectionType': device.connectionType,
        'origDeviceType': device.deviceType,
        'type': deviceType,
        'name': name,
        'ipAddress': device.ipAddress,
        'ipSafe': device.ipAddress.replace(/\./g, '_'),
        'origDevice': device,
        'specialText': specText,
        'specialImageSuffix': specImageSuffix
    };
}

function openDeviceFromInfo (deviceInfo, connectionType, onError, onSuccess)
{
    openDeviceFromAttributes(
        deviceInfo.deviceType,
        deviceInfo.serialNumber,
        deviceInfo.ipAddress,
        connectionType,
        onError,
        onSuccess
    );
}

function finishDeviceRecord (listingDict, deviceInfo, callback)
{
    var listingEntry = getListingEntry(listingDict, deviceInfo);

    console.log('..open..');
    openDeviceFromInfo(
        deviceInfo,
        deviceInfo.connectionType,
        function () {callback();},
        function (device) {
            // TODO: This needs to change when rwMany can handle multiple types.
            var name = device.readSync('DEVICE_NAME_DEFAULT');
            var hardwareInstalled;
            var record;

            if (deviceInfo.deviceType == 7) {
                hardwareInstalled = device.readSync('HARDWARE_INSTALLED') !== 0;
            } else {
                hardwareInstalled = false;
            }

            if (hardwareInstalled) {
                record = createDeviceListingRecord(
                    deviceInfo,
                    name,
                    ' Pro',
                    '-pro'
                );
            } else {
                record = createDeviceListingRecord(
                    deviceInfo,
                    name,
                    '',
                    ''
                );
            }

            listingEntry.devices.push(record);
            device.closeSync();
            callback();
        }
    );
}

var consolidateDevices = function (listing) {
    var existingDevice;
    var newDevice;
    var deviceListing = dict();
    var devices = listing.devices;
    var numDevices = devices.length;

    for (var i=0; i<numDevices; i++) {
        newDevice = devices[i];
        existingDevice = deviceListing.get(newDevice.serial.toString(), null);
        if (existingDevice !== null) {
            newDevice.connectionTypes.push.apply(
                newDevice.connectionTypes,
                existingDevice.connectionTypes
            );
        }
        deviceListing.set(newDevice.serial.toString(), newDevice);
    }

    var retList = [];
    deviceListing.forEach(function (value, key) {
        retList.push(value);
    });

    listing.devices = retList;
};

/**
 * Get a list of devices currently visible by to this computer.
 *
 * @param {function} onError The funciton to call if an error is encountered.
 * @param {function} onSuccess The function to call after the list of devices
 *      has been collected.
 * @return {Array} An Array of Objects with the keys "name" and "devices". The
 *      value of "name" is a String with the name of the device type (ex: "T7").
 *      The value of "devices" is a list of Objects with the keys "serial",
 *      "connectionTypes", "type", and "name".
**/
exports.getDevices = function (onError, onSuccess)
{
    labjack_driver.listAll(
        onError,
        function (driverListing) {
            var listingDict = dict();
            async.each(
                driverListing,
                function (deviceInfo, callback) {
                    finishDeviceRecord(listingDict, deviceInfo, callback);
                },
                function (err) {
                    if (err) {
                        alert(err);
                        return;
                    }

                    var listing = [];
                    listingDict.forEach(function (value, key) {
                        listing.push(value);
                    });

                    for (var i=0; i<listing.length; i++)
                        consolidateDevices(listing[i]);

                    markConnectedDevices(listing, onSuccess);
                }
            );
        }
    );
};

/**
 * Open a connection to a device.
 *
 * @param {String} serial The serial number of the device to open.
 * @param {String} connType The type of connection to open to the device.
 *      Examples include "USB", "Ethernet", and "WiFi".
 * @param {String} deviceType The type of device that should be opened. Examples
 *      include "T7" and "Digit-TL".
 * @param {function} onError The function to call if an error is encountered.
 * @param {function} onSuccess The function to call afte the device has been
 *      successfully opened.
**/
exports.openDevice = function (serial, ipAddress, connType, deviceType, onError,
    onSuccess)
{
    openDeviceFromAttributes(
        deviceType,
        serial,
        ipAddress,
        connType,
        onError,
        function (innerDevice) {
            var device = new Device(innerDevice, serial, connType, deviceType);
            onSuccess(device);
        }
    );
};

/**
 * Close the connection to a device.
 *
 * @param {Device} device The device to close the connection to.
 * @param {function} onSuccess The function to call after the connection to the
 *      device is successfully closed.
 * @param {function} onError The function to call if an error is encountered
 *      while trying to close a device.
**/
exports.closeDevice = function(device, onSuccess, onError)
{
    device.close(onError, function() {
        onSuccess(device);
    });
};
<commit_msg>Read device attributes in series.<commit_after>/**
 * Device controller that produces test devices.
 *
 * Device controller that produces test devices and simulates device
 * interactions.
 *
 * @author A. Samuel Pottinger (LabJack, 2013)
**/

var async = require('async');
var dict = require('dict');
var q = require('q');
var labjack_nodejs = require('labjack-nodejs');
var labjack_driver = new labjack_nodejs.driver();

var LJM_DT_T7 = labjack_nodejs.driver_const.LJM_DT_T7.toString();
var DEVICE_TYPE_NAMES = dict({
    '7': 'T7'
});

var CONNECT_TYPE_USB = 1;
var CONNECTION_TYPE_NAMES = dict({
    '1': 'USB',
    '3': 'Ethernet',
    '4': 'Wifi'
});

/**
 * Object with information about a device.
 *
 * @param {String} serial The serial number for the device.
 * @param {String} connectionType The type of connection used to communicate
 *      with the device. Examples include "USB", "Ethernet", and "WiFi".
 * @param {String} deviceType The type of model this device is. Examples include
 *      T7 and Digit-TL.
**/
var Device = function (device, serial, connectionType, deviceType)
{
    this.device = device;
    this.cachedName = null;

    /**
     * Get the serial number for this device.
     *
     * @return {String} The serial number for this device.
    **/
    this.getSerial = function () {
        return serial;
    };

    /**
     * Get the type of connection being used to communicate with this device.
     *
     * Get the type of connection being used to communicate with this device.
     * Examples include "USB", "Ethernet", and "WiFi".
     *
     * @return {String} The type of connection being used to communicate with
     *      this device.
    **/
    this.getConnectionType = function () {
        return connectionType;
    };

    /**
     * Get the type of model this device is.
     *
     * Get a String describing what kind of device this is. Examples include
     * "T7" and "Digit-TL".
     *
     * @return {String} A description of the type of device this is.
    **/
    this.getDeviceType = function () {
        return DEVICE_TYPE_NAMES.get(String(deviceType), 'Other');
    };

    /**
     * Get the user-assigned name for this device.
     *
     * Get the name of this device as assigned by a previous authorized user
     * (name not set by default).
     *
     * @return {String} The name of this device.
    **/
    this.getName = function () {
        if (this.cachedName === null)
            this.cachedName = this.device.readSync('DEVICE_NAME_DEFAULT');
        return this.cachedName;
    };

    // TODO
    this.getFirmwareVersion = function () {
        return this.device.readSync('FIRMWARE_VERSION');
    };

    // TODO
    this.getBootloaderVersion = function () {
        return this.device.readSync('BOOTLOADER_VERSION');
    };

    this.writeMany = function (addresses, values) {
        var deferred = q.defer();

        console.log(addresses, values);
        this.device.writeMany(
            addresses,
            values,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.readMany = function (addresses) {
        var deferred = q.defer();

        this.device.readMany(
            addresses,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.writeAsync = function(address, value) {
        var deferred = q.defer();

        this.device.write(
            address,
            value,
            function (err) {
                deferred.reject(err);
            },
            function (results) {
                deferred.resolve(results);
            }
        );

        return deferred.promise;
    };

    this.write = function (address, value) {
        this.device.writeSync(address, value);
    };

    this.read = function (address) {
        return this.device.readSync(address);
    };

    this.close = function (onError, onSuccess) {
        this.device.close(onError, onSuccess);
    };

    this.setName = function (newName) {
        this.write('DEVICE_NAME_DEFAULT', newName);
        this.cachedName = newName;
    };
};

// TODO: Cannot rely on serial number alone.
// TODO: This should be in a seperate module.
/**
 * A record keeper that holds a list of devices.
 *
 * A record keeper that holds a list of devices. Example usages include holding
 * a list of devices that are currently open.
**/
function DeviceKeeper()
{
    var devices = dict();

    /**
     * Add a new device to this keeper.
     *
     * @param {Device} device The device to add to this keeper.
    **/
    this.addDevice = function(device)
    {
        devices.set(device.getSerial(), device);
    };

    /**
     * Deermine how many devices this keeper has in it.
     *
     * @return {Number} The number of devices this keeper currently has in it.
    **/
    this.getNumDevices = function()
    {
        return devices.size;
    };

    /**
     * Remove a device from this keeper.
     *
     * @param {Device} device The device or equivalent device to remove from
     *      this keeper. The device removed from the keeper will be the one with
     *      the same serial number.
    **/
    this.removeDevice = function(device)
    {
        if(devices.has(device.getSerial()))
            devices.delete(device.getSerial());
    };

    /**
     * Get a device from this keeper.
     *
     * Get a device from this keeper based on a serial number. Will return null
     * if the device is not in this keeper.
     *
     * @return {Device} The device with the given serial number of null if no
     *      device by that serial number is in this keeper.
    **/
    this.getDevice = function(serial)
    {
        if(devices.has(serial))
            return devices.get(serial);
        else
            return null;
    };

    this.getDevices = function()
    {
        var retList = [];
        devices.forEach(function(value, key) {retList.push(value);});
        return retList;
    };

    this.getDeviceSerials = function()
    {
        var retList = [];
        devices.forEach(function(value, key) {retList.push(key);});
        return retList;
    };

    this.updateDevice = function (device) {
        this.removeDevice(device);
        this.addDevice(device);
    };
}

var deviceKeeperInstance = null;

function openDeviceFromAttributes (deviceType, serialNumber, ipAddress,
    connectionType, onError, onSuccess)
{
    var device;
    if (connectionType == CONNECT_TYPE_USB) {
        device = new labjack_nodejs.device();
        device.open(
            deviceType,
            connectionType,
            String(serialNumber),
            onError,
            function () { onSuccess(device); }
        );
    } else {
        device = new labjack_nodejs.device();
        device.open(
            deviceType,
            connectionType,
            ipAddress,
            onError,
            function () { onSuccess(device); }
        );
    }
}

/**
 * Get the device keeper singlton instance maintaining the list of open devices.
 *
 * @return {DeviceKeeper} The device keeper used system wide that maintains a
 *      list of all open devices.
**/
exports.getDeviceKeeper = function()
{
    if(deviceKeeperInstance === null)
        deviceKeeperInstance = new DeviceKeeper();
    return deviceKeeperInstance;
};

function markConnectedDevices(devices, onSuccess, onError)
{
    var devicesOfType;
    var device;

    var connectedSerials = exports.getDeviceKeeper().getDeviceSerials();

    var devicesLen = devices.length;
    var connectedDevices = [];
    for(var i=0; i<devicesLen; i++)
    {
        devicesOfType = devices[i].devices;
        var devicesOfTypeLen = devicesOfType.length;
        for(var j=0; j<devicesOfTypeLen; j++)
        {
            device = devicesOfType[j];
            if (connectedSerials.indexOf(device.serial.toString()) != -1)
                connectedDevices.push(device);
            else
                device.connected = false;
        }
    }

    async.each(
        connectedDevices,
        function (item, callback) {
            openDeviceFromAttributes(
                device.origDeviceType,
                device.serial,
                device.ipAddress,
                device.origConnectionType,
                function (err) {
                    console.log('===err===');
                    console.log(err);
                    device.connected = false;
                    callback();
                },
                function (newInner) {
                    var convConnType = device.origConnectionType;
                    var newDecoratedDevice = new Device(
                        newInner,
                        String(device.serial),
                        convConnType,
                        device.origDeviceType
                    );
                    exports.getDeviceKeeper().updateDevice(newDecoratedDevice);
                    device.connected = true;
                    callback();
                }
            );
        },
        function (err) {
            onSuccess(devices);
        }
    );
}

function getListingEntry (listingDict, device)
{
    var deviceType = String(device.deviceType);

    if (!listingDict.has(deviceType)) {
        listingDict.set(
            deviceType,
            {
                'name': DEVICE_TYPE_NAMES.get(deviceType, 'other'),
                'devices': []
            }
        );
    }

    return listingDict.get(deviceType);
}

function createDeviceListingRecord (device, name, specText, specImageSuffix)
{
    var connectionType = CONNECTION_TYPE_NAMES.get(
        String(device.connectionType), 'other');
    var deviceType = DEVICE_TYPE_NAMES.get(String(device.deviceType), 'other');

    return {
        'serial': device.serialNumber,
        'connectionTypes': [connectionType],
        'origConnectionType': device.connectionType,
        'origDeviceType': device.deviceType,
        'type': deviceType,
        'name': name,
        'ipAddress': device.ipAddress,
        'ipSafe': device.ipAddress.replace(/\./g, '_'),
        'origDevice': device,
        'specialText': specText,
        'specialImageSuffix': specImageSuffix
    };
}

function openDeviceFromInfo (deviceInfo, connectionType, onError, onSuccess)
{
    openDeviceFromAttributes(
        deviceInfo.deviceType,
        deviceInfo.serialNumber,
        deviceInfo.ipAddress,
        connectionType,
        onError,
        onSuccess
    );
}

function finishDeviceRecord (listingDict, deviceInfo, callback)
{
    var listingEntry = getListingEntry(listingDict, deviceInfo);

    console.log('..open..');
    openDeviceFromInfo(
        deviceInfo,
        deviceInfo.connectionType,
        function (err) {
            console.log(err);
            record = createDeviceListingRecord(
                deviceInfo,
                '[ could not read name ]',
                '',
                ''
            );
            listingEntry.devices.push(record);
            callback();
        },
        function (device) {
            // TODO: This needs to change when rwMany can handle multiple types.
            var name = device.readSync('DEVICE_NAME_DEFAULT');
            var hardwareInstalled;
            var record;

            if (deviceInfo.deviceType == 7) {
                hardwareInstalled = device.readSync('HARDWARE_INSTALLED') !== 0;
            } else {
                hardwareInstalled = false;
            }

            if (hardwareInstalled) {
                record = createDeviceListingRecord(
                    deviceInfo,
                    name,
                    ' Pro',
                    '-pro'
                );
            } else {
                record = createDeviceListingRecord(
                    deviceInfo,
                    name,
                    '',
                    ''
                );
            }

            listingEntry.devices.push(record);
            device.closeSync();
            callback();
        }
    );
}

var consolidateDevices = function (listing) {
    var existingDevice;
    var newDevice;
    var deviceListing = dict();
    var devices = listing.devices;
    var numDevices = devices.length;

    for (var i=0; i<numDevices; i++) {
        newDevice = devices[i];
        existingDevice = deviceListing.get(newDevice.serial.toString(), null);
        if (existingDevice !== null) {
            newDevice.connectionTypes.push.apply(
                newDevice.connectionTypes,
                existingDevice.connectionTypes
            );
        }
        deviceListing.set(newDevice.serial.toString(), newDevice);
    }

    var retList = [];
    deviceListing.forEach(function (value, key) {
        retList.push(value);
    });

    listing.devices = retList;
};

/**
 * Get a list of devices currently visible by to this computer.
 *
 * @param {function} onError The funciton to call if an error is encountered.
 * @param {function} onSuccess The function to call after the list of devices
 *      has been collected.
 * @return {Array} An Array of Objects with the keys "name" and "devices". The
 *      value of "name" is a String with the name of the device type (ex: "T7").
 *      The value of "devices" is a list of Objects with the keys "serial",
 *      "connectionTypes", "type", and "name".
**/
exports.getDevices = function (onError, onSuccess)
{
    labjack_driver.listAll(
        onError,
        function (driverListing) {
            var listingDict = dict();
            async.eachSeries(
                driverListing,
                function (deviceInfo, callback) {
                    finishDeviceRecord(listingDict, deviceInfo, callback);
                },
                function (err) {
                    if (err) {
                        alert(err);
                        return;
                    }

                    var listing = [];
                    listingDict.forEach(function (value, key) {
                        listing.push(value);
                    });

                    for (var i=0; i<listing.length; i++)
                        consolidateDevices(listing[i]);

                    markConnectedDevices(listing, onSuccess);
                }
            );
        }
    );
};

/**
 * Open a connection to a device.
 *
 * @param {String} serial The serial number of the device to open.
 * @param {String} connType The type of connection to open to the device.
 *      Examples include "USB", "Ethernet", and "WiFi".
 * @param {String} deviceType The type of device that should be opened. Examples
 *      include "T7" and "Digit-TL".
 * @param {function} onError The function to call if an error is encountered.
 * @param {function} onSuccess The function to call afte the device has been
 *      successfully opened.
**/
exports.openDevice = function (serial, ipAddress, connType, deviceType, onError,
    onSuccess)
{
    openDeviceFromAttributes(
        deviceType,
        serial,
        ipAddress,
        connType,
        onError,
        function (innerDevice) {
            var device = new Device(innerDevice, serial, connType, deviceType);
            onSuccess(device);
        }
    );
};

/**
 * Close the connection to a device.
 *
 * @param {Device} device The device to close the connection to.
 * @param {function} onSuccess The function to call after the connection to the
 *      device is successfully closed.
 * @param {function} onError The function to call if an error is encountered
 *      while trying to close a device.
**/
exports.closeDevice = function(device, onSuccess, onError)
{
    device.close(onError, function() {
        onSuccess(device);
    });
};
<|endoftext|>


<commit_before>
var dotBox;

dotBox = dotBox || {};

/**
 * Game configuration options.
 * @typedef     {Object}    gameConfig
 * @property    {number}    dotCountLength     - The number of game dots across the length (x-axis) of the board.
 * @property    {number}    dotCountWidth      - The number of game dots across the width (y-axis) of the board.
 * @property    {number}    playerCount        - The number of players.
 *
 */

/**
 * Creates a new game engine.
 * @function gameEngine
 * @param   {gameConfig}    - The game configuration options.
 *
 */
dotBox.gameEngine = function gameEngine(config) {

    var DEFAULT_PLAYER_COUNT = 2,
        DEFAULT_DOT_COUNT_LENGTH = 10,
        DEFAULT_DOT_COUNT_WIDTH = 10,
        _playerCount,
        _dotCountLength,
        _dotCountWidth,
        _boxCountLength,
        _boxCountWidth,
        _lineCountHorizontal,
        _lineCountVertical,
        _horizontalLineStates,
        _verticalLineStates,
        i;

    configureGame(config);

    /**
     * Returns the number of players for the game.
     * @function getPlayerCount
     * @returns {number}
     */
    function getPlayerCount() {
        return _playerCount;
    }

    /**
     * The number of dots across the game board's length (x-axis).
     * @function getDotCountLength
     * @returns {number}
     */
    function getDotCountLength() {
        return _dotCountLength;
    };

    /**
     * The number of boxes across the game board's length (x-axis).
     * @function getBoxCountLength
     * @returns {number}
     */
    function getBoxCountLength() {
        return _boxCountLength;
    };

    /**
     * The number of connector lines that can be placed horizontally.
     * @function getLineCountHorizontal
     * @returns {number}
     */
    function getLineCountHorizontal() {
        return _lineCountHorizontal;
    };

    /**
     * The number of dots across the game board's width (y-axis).
     * @function getDotCountWidth
     * @returns {number}
     */
    function getDotCountWidth() {
        return _dotCountWidth;
    };

    /**
     * The number of boxes across the game board's width (y-axis).
     * @function getDotCountWidth
     * @returns {number}
     */
    function getBoxCountWidth() {
        return _boxCountWidth;
    };

    /**
     * The number of connector lines that can be placed vertically.
     * @function getLineCountVertical
     * @returns {number}
     */
    function getLineCountVertical() {
        return _lineCountVertical;
    };

    /**
     * Checks to see if the specified horizontal line is closed.
     *
     * @param   {number}    row     The row index of the h-line.
     *                              Valid values are 0 to dotCountWidth-1.
     *
     * @param   {number}    col     The column index of the h-line.
     *                              Valid values are 0 to boxCountLength-1.
     *
     * @returns {boolean}           true if the line is closed (connected),
     *                              or false if the line is open.
     */
    function isHzLineClosed(row, col) {

        var index = 0,
            isClosed;

        if((row < 0) || (row > (_dotCountWidth - 1))) {
            throw new RangeError("row must be between 0 and dotCountWidth - 1.");
        }

        if((col < 0) || (col > (_boxCountLength - 1))) {
            throw new RangeError("col must be between 0 and boxCountLength - 1.");
        }

        index = (row * _boxCountLength) + col;

        isClosed = _horizontalLineStates[index];

        return isClosed;

    }

    /**
     * Checks to see if the specified vertical line is closed.
     *
     * @param   {number}    row     The row index of the v-line.
     *                              Valid values are 0 to boxCountWidth-1.
     *
     * @param   {number}    col     The column index of the v-line.
     *                              Valid values are 0 to dotCountLength-1.
     *
     * @returns {boolean}           true if the line is closed (connected),
     *                              or false if the line is open.
     */
    function isVtLineClosed(row, col) {

        var index = 0,
            isClosed;

        if((row < 0) || (row > (_boxCountWidth - 1))) {
            throw new RangeError("row must be between 0 and boxCountWidth - 1.");
        }

        if((col < 0) || (col > (_dotCountLength - 1))) {
            throw new RangeError("col must be between 0 and dotCountLength - 1.");
        }

        index = (row * getDotCountLength()) + col;

        isClosed = _verticalLineStates[index];

        return isClosed;

    }

    /**
     * Validates the game configuration passed to the constructor.
     * and assigns member values.
     * @method
     * @param   {gameConfig}    The game configuration options.
     */
    function configureGame(config)
    {
        if(!config) {
            config = {};
        }

        if(config.dotCountLength === undefined || config.dotCountLength === null) {
            _dotCountLength = DEFAULT_DOT_COUNT_LENGTH;
        } else {
            _dotCountLength = parseInt(config.dotCountLength);
        }

        if(config.dotCountWidth === undefined || config.dotCountWidth === null) {
            _dotCountWidth = DEFAULT_DOT_COUNT_WIDTH;
        } else {
            _dotCountWidth = parseInt(config.dotCountWidth);
        }

        if(config.playerCount === undefined || config.playerCount === null) {
            _playerCount = DEFAULT_PLAYER_COUNT;
        } else {
            _playerCount = parseInt(config.playerCount);
        }

        if(isNaN(_dotCountLength)) {
            throw new TypeError("dotCountLength is not a number.")
        }

        if(isNaN(_dotCountWidth)) {
            throw new TypeError("dotCountWidth is not a number.")
        }

        if(isNaN(_playerCount)) {
            throw new TypeError("playerCount is not a number.")
        }

        if(_dotCountLength < 3) {
            throw new RangeError("dotCountLength must be three or more")
        }

        if(_dotCountWidth < 3) {
            throw new RangeError("dotCountWidth must be three or more")
        }

        if(_playerCount < 2) {
            throw new RangeError("playerCount must two or more")
        }

        _boxCountLength = _dotCountLength - 1;
        _boxCountWidth = _dotCountWidth - 1;

        _lineCountHorizontal = _boxCountLength  * _dotCountWidth;
        _lineCountVertical = _boxCountWidth * _dotCountLength;

        _horizontalLineStates = [];
        for(i = 0; i < _lineCountHorizontal; i++) {
            _horizontalLineStates[i] = false;
        }

        _verticalLineStates = [];
        for(i = 0; i < _lineCountVertical; i++) {
            _verticalLineStates[i] = false;
        }

    }

    return {

        getDotCountLength: getDotCountLength,
        getBoxCountLength: getBoxCountLength,
        getLineCountHorizontal: getLineCountHorizontal,
        getLineCountVertical: getLineCountVertical,
        getDotCountWidth: getDotCountWidth,
        getBoxCountWidth: getBoxCountWidth,
        getPlayerCount: getPlayerCount,
        isHzLineClosed: isHzLineClosed,
        isVtLineClosed: isVtLineClosed

    };

};

<commit_msg>Delete dotBox.GameEngine.js<commit_after><|endoftext|>